57
Guia do programador de NQC Versão 2.5 a4 Por Dave Baum Traduzido por Ricardo Ortins

Versão 2.5 a4 Por Dave Baum · 2008. 11. 24. · _____Guia do programador de NQC_____ 1 1. Introdução NQC significa Not Quite C (Não completamente C) e, é uma linguagem simples

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

  • Guia do programador de NQC

    Versão 2.5 a4 Por Dave Baum

    Traduzido por Ricardo Ortins

  • ÍNDICE

    1. Introdução..............................................................................................................1

    2. Linguagem NQC....................................................................................................2

    2.1 Regra léxica............................................................................................................2

    2.1.1. Comentários......................................................................................................2

    2.1.2. Espaço em branco.............................................................................................2

    2.1.3. Constantes numéricas.......................................................................................3

    2.1.4. Identificadores e palavras reservadas...............................................................3

    2.2. Estrutura do programa...........................................................................................4

    2.2.1. Tarefas..............................................................................................................4

    2.2.2. Funções.............................................................................................................4

    2.2.3. Sub-rotinas........................................................................................................7

    2.2.4. Variáveis...........................................................................................................8

    2.2.5. Matrizes..........................................................................................................10

    2.3. Instruções............................................................................................................10

    2.3.1. Declaração de variáveis..................................................................................10

    2.3.2. Atribuição.......................................................................................................11

    2.3.3. Estruturas de controle.....................................................................................11

    2.3.4. Controle de acesso e eventos..........................................................................15

    2.3.5. Outras instruções............................................................................................17

    2.4. Expressões...........................................................................................................17

    2.4.1. Condicionais...................................................................................................19

    2.5. O pré-processador................................................................................................20

    2.5.1. # include.........................................................................................................20

    2.5.2. # define...........................................................................................................20

    2.5.3. Compilação condicional.................................................................................21

    2.5.4. Iniciação do programa....................................................................................21

    2.5.5. Armazenamento de reserva............................................................................21

    3. NQC API..............................................................................................................22

    3.1. Sensores...............................................................................................................22

    3.1.1. Tipos e modos RCX, CyberMaster................................................................22

    3.1.2. Informação do sensor.....................................................................................25

    3.1.3. Sensor de luz do Scout ..................................................................................26

  • 3.1.4. Sensor de luz do Spybotics Spy.....................................................................27

    3.2. Saídas.................................................................................................................27

    3.2.1. Funções básicas.............................................................................................27

    3.2.2. Outras funções...............................................................................................28

    3.2.3. Controle Global RCX2, Scout.......................................................................30

    3.2.4. Saídas de Spybotics.......................................................................................31

    3.3. Som.....................................................................................................................31

    3.4. Display LCD RCX............................................................................................32

    3.5. Comunicação......................................................................................................33

    3.5.1. Mensagens RCX, Scout.................................................................................33

    3.5.2. Série RCX2, Scout.........................................................................................34

    3.5.3. VLL (Link de luz visível), Scout...................................................................36

    3.6. Temporizadores..................................................................................................36

    3.7. Contadores RCX2, Scout, Spy...........................................................................37

    3.8. Controle de acesso RCX2, Scout, Spy...............................................................38

    3.9. Evento RCX2, Scout..........................................................................................38

    3.9.1. Eventos do RCX, spy....................................................................................39

    3.9.2. Eventos do Scout...........................................................................................43

    3.10. Registro de dados RCX....................................................................................45

    3.11. Características gerais........................................................................................46

    3.12. Características específicas do RCX..................................................................47

    3.13. Características específicas do Scout.................................................................48

    3.14. Características específicas do Cybermaster......................................................48

    4. Detalhes técnicos.................................................................................................50

    4.1. A instrução ASN.................................................................................................50

    4.2. Fontes de dados..................................................................................................52

    5. Nota do tradutor...................................................................................................54

  • ____________________Guia do programador de NQC________________________

    1

    1. Introdução

    NQC significa Not Quite C (Não completamente C) e, é uma linguagem simples

    para programar vários produtos LEGO MINDSTORMS. Algumas das características de

    NQC dependem do produto MINDSTORMS que se utilize. NQC se refere aos

    diferentes blocos inteligentes como os modelos. Atualmente NQC suporta quatro

    diferentes modelos: RCX, RCX2 (Um RCX que executa um firmware versão 2.0),

    CyberMaster, Scout e Spybotics.

    Todos os modelos têm um intérprete de bytes (proporcionado por Lego) que pode

    ser utilizado para executar programas. O compilador NQC converte um programa fonte

    em LEGO Bytecode, o qual pode ser executado no próprio modelo. Ainda que as

    estruturas de processamento e de controle sejam muito similares a C, NQC não é uma

    linguagem de propósito geral

    há muitas restrições que são produtos das limitações do

    intérprete de código de bytes Lego.

    Logicamente o NQC se define em duas partes diferentes.

    A linguagem NQC descreve a sintaxe utilizada ao escrever programas. O NQC

    API descreve as funções dos sistemas, constantes e macros que se podem usar nos

    programas. Esta API define-se em um arquivo especial incluído no compilador.

    Por definição, esse arquivo sempre se processa antes de compilar o programa.

    Esse documento descreve ambos: a linguagem NQC e o NQC API. Em resumo,

    proporciona a informação necessária para escrever programas em NQC. Dado que há

    várias interfaces para NQC, esse documento não descreve como usar nenhuma

    implementação de NQC específica. Consulte a documentação oferecida com a

    ferramenta NQC, assim como o manual de usuário de NQC para informações

    específicas para essa implementação.

    Se deseja informação em documentação atualizada de NQC, visite o site web de

    NQC na seguinte direção:

    http:// www.baumfamily.org/nqc

  • ____________________Guia do programador de NQC________________________

    2

    2. Linguagem NQC

    Esta sessão descreve a própria linguagem NQC. Inclui as regras léxicas usadas

    pelo compilador, a estrutura dos programas, sentenças e expressões e, o funcionamento

    do processador.

    2.1. Regras Léxicas

    As regras léxicas descrevem como o NQC divide um arquivo fonte em sinais

    individuais. Inclui como estão escritos os comentários, o manejo dos espaços em branco

    e os caracteres válidos para identificadores.

    2.1.1. Comentários

    NQC suporta dois tipos de comentários. O primeiro tipo (comentário C

    tradicional) começa com /* e termina com */ . Podem conter várias linhas, mas não

    podem adicionar.

    /* isto é um comentário*/

    /* isto é um comentário

    de duas linhas */

    /* outro comentário...

    /* tentando adicionar...

    finalizando o comentário de dentro... */

    Esse texto já não é um comentário! */

    A segunda classe de comentário começa com // e termina com uma nova linha

    (conhecido às vezes como comentário estilo c++).

    // um comentário de uma linha simples

    O compilador ignora os comentários. Seu único propósito é permitir ao

    programador documentar o código fonte.

    2.1.2. Espaços em branco

    O espaço em branco (espaços, tabulações e saltos de linha) usa-se para separar

    sinais e para fazer os programas mais legíveis. Contanto que se distingam, os sinais, não

    tem efeito no programa adicionar ou suprimir espaços em branco. Por exemplo, as

    seguintes linhas de código têm o mesmo significado:

  • ____________________Guia do programador de NQC________________________

    3

    x=2;

    x = 2 ;

    Alguns dos operadores de c++ estão formados por múltiplos caracteres. Para

    preservar esses sinais não se deve inserir espaços em branco entre eles. No exemplo

    seguinte, a primeira linha usa um operador de avanço para direita ( >> ), mas na

    segunda linha o espaço adicionado faz com que os símbolos > se interpretem como

    dois elementos separados e em conseqüência se gera um erro.

    x = 1 >> 4; // dá a X o valor de 1 deslocado para direita 4 bits

    x = 1 > > 4; // errado

    2.1.3. Constantes Numéricas

    As constantes numéricas podem se escrever tanto em formato decimal como

    hexadecimal. As constantes decimais consistem em um ou mais dígitos decimais. As

    constantes hexadecimais começam com 0x ou 0X seguidos de um ou mais dígitos

    hexadecimais.

    x = 10; // dá a x o valor 10

    x = 0x10; // dá a x o valor 16 (10 hex)

    2.1.4. Identificadores e palavras reservadas

    Usam-se os identificadores para nomes de tarefas, variáveis e funções. O primeiro

    caractere de um identificador deve ser uma letra maiúscula ou minúscula ou sublinhado

    ( _ ). Os caracteres restantes podem ser letras números e sublinhado.

    Se reserva um número potencial de identificadores para uso da própria linguagem

    de NQC. Essas palavras se denominam palavras reservadas e não se podem usar como

    identificadores. Abaixo se oferece uma lista completa de palavras reservadas:

    __event_src __res __tasked abs

    __nolist __sensor __type acquire

    asm do int sub

    break else monitor switch

    case false repeat task

    catch for return true

    const goto sign void

    continue if start while

    default inline stop

  • ____________________Guia do programador de NQC________________________

    4

    2.2. Estrutura do programa

    Um programa NQC compõe-se de blocos de código e variáveis globais. Existem

    três tipos de blocos de código: tarefas, funções em linha e sub-rotinas. Cada tipo de

    blocos de código tem suas próprias características e restrições particulares, mas todos

    compartilham uma estrutura comum.

    2.2.1.Tarefas

    O RCX suporta multitarefas, de modo que uma tarefa em NQC corresponde a uma

    tarefa RCX. As tarefas definem-se por meios da palavra reservada task utilizando a

    seguinte sintaxe:

    task nome()

    {

    // o código da tarefa se escreve aqui

    }

    O nome da tarefa pode ser qualquer identificador legal. Um programa deve ter ao

    menos uma tarefa chamada main

    que se inicia cada vez que se executa o programa. O

    número máximo de tarefas depende do modelo

    RCX suporta 10 tarefas, cybermaster 4

    e, scout 6.

    O corpo de uma tarefa consiste em uma lista de instruções. As tarefas podem

    iniciar-se e parar utilizando as instruções start e stop (descritas na sessão intitulada

    instruções). Existe também um comando RCX API stopalltasks, que pára todas as

    tarefas em funcionamento neste momento.

    2.2.2. Funções

    Às vezes é útil agrupar um conjunto de instruções em uma só função, que pode ser

    chamada quando seja necessário. NQC suporta funções com argumentos, mas não

    valores de retorno. As funções se definem com as seguintes sintaxes:

    void nome(lista_de_argumentos)

    {

    // corpo da função

    }

    A palavra reservada void é conseqüência da herança de NQC

    em C as funções

    se especificam com o tipo de dados que devolvem. As funções que não devolvem dados

    devolvem void. A devolução de dados não tem suporte em NQC, de modo que todas as

    funções se declaram usando a palavra reservada void.

  • ____________________Guia do programador de NQC________________________

    5

    A lista de argumentos pode estar vazia ou pode conter uma ou mais definições de

    argumento. Um argumento define-se por seu tipo, seguido de seu nome. Os argumentos

    múltiplos separam-se por vírgulas. Todos os valores em RCX representam-se como

    inteiros de 16 bits consígnos. No entanto, NQC suporta quatro tipos diferentes de

    argumentos que correspondem a diferentes restrições e modos de passo do argumento.

    Tipo Significado Restrição

    Int Passa Valor Nenhuma

    Const Int Passa Valor Só se pode usar constantes

    Int& Passa Referência Só se pode usar variáveis

    Const Int& Passa Referência A função não pode modificar argumentos

    Os argumentos de tipo int passam-se por valores da função que chama para

    função iniciada. Isto quer dizer, que o compilador deve definir uma variável temporal

    que armazene o argumento. Não existem restrições para o tipo de valor que se pode

    usar. No entanto, já que a função trabalha com a cópia do argumento em si, qualquer

    mudança que sofra o valor não se vê na função que se chama. No exemplo abaixo a

    função foo tenta estabelecer o valor de seu argumento em 2. Isto é perfeitamente legal,

    mas dado que foo funciona como uma cópia do argumento original a variável Y da

    tarefa principal não sofrerá mudanças.

    void foo(int x)

    {

    x = 2;

    }

    task main()

    {

    int y = 1; // y é agora igual a 1

    foo (y); // y continua igual a 1!

    }

    O segundo tipo de argumento, const int, também passa-se por valor, mas com a

    restrição de só poder usar valores constantes (quer dizer, números). Isso é muito

    importante já que existem várias funções RCX que só funcionam com argumentos

    constantes:

    void foo(const int x)

    {

    PlaySound (x); // ok

  • ____________________Guia do programador de NQC________________________

    6

    x = 1; // erro não pode modificar um argumento

    }

    task main()

    {

    foo (2); // ok

    foo (4*5 ); // ok expressão constante

    foo (x); // erro - x não é uma constante

    }

    O terceiro tipo, int &, passa argumentos ou referências em vez de passar valor.

    Isto permite que a função chamada modifique o valor e, faça visíveis as mudanças na

    função que chama. No entanto, só se podem usar variáveis quando se chama uma

    função usando argumento int &:

    void foo(int &x)

    {

    x = 2;

    }

    task main()

    {

    int y = 1; // y é igual a 1

    foo (y); // y é agora igual a 2

    foo (2); // erro só se permitem variáveis

    }

    O último tipo, const int &, é muito pouco freqüente. Também se passa por

    referência, mas com a restrição de que a função chamada não lhe permite modificar o

    valor. A causa dessa restrição: o compilador pode passar qualquer coisa (não só

    variáveis) à função usando esse tipo de argumento. Em geral esta é a forma mais

    eficiente de passar argumentos em NQC.

    Existe uma diferença importante entre argumentos int e argumentos const int & .

    Um argumento int passa-se por valor, de modo que no caso de uma expressão dinâmica

    (como a leitura de um sensor) o valor lê uma vez e se armazena. Com os argumentos

    const int & , a expressão lê cada vez que é usada na função:

    void foo(int x)

    {

    if (x == x) // isto sempre é verdade

    PlaySound(SOUND_CLICK);

    }

    void bar(const int &x)

    {

  • ____________________Guia do programador de NQC________________________

    7

    if (x == x) //pode não ser verdade..

    // o valor poderia mudar

    PlaySound(SOUND_CLICK);

    }

    task main()

    {

    foo(SENSOR_1); // reproduz som

    bar(2); // reproduz som

    bar(SENSOR_1); // poderia não reproduzir som

    }

    As funções devem chamar com o número (e tipo) correto de argumentos.

    O exemplo seguinte mostra diferentes chamadas legais e ilegais da função foo:

    void foo(int bar, const int baz)

    {

    // faz algo aqui...

    }

    task main()

    {

    int x; // declarar variável x

    foo (1,2); // ok

    foo (x,2); // ok

    foo (2,x); // erro segundo argumento não constante!

    foo (2); // erro número equivocado de argumentos!

    }

    As funções NQC sempre se expandem como funções em linha. Isto significa que

    cada chamada a uma função faz com que se inclua no programa outra cópia do código

    da função. Se não se usar com sensatez, as funções em linha fazem com que o tamanho

    do código seja excessivo.

    2.2.3. Sub-rotinas

    A diferença das funções em linha é que as sub-rotinas permitem que se

    compartilhem uma única cópia do fragmento de código entre diferentes funções

    chamadoras. Isto faz com que seja muito mais eficaz no uso do espaço que nas funções

    em linha, mas devido a algumas limitações do interpretador de códigos de bytes Lego as

    sub-rotinas possuem algumas restrições significativas. Em primeiro lugar, as sub-rotinas

    não podem utilizar nenhum argumento. Segundo, uma sub-rotina não pode chamar a

    outra sub-rotina. Por último, o número máximo de sub-rotinas se limita a 8 para o RCX,

  • ____________________Guia do programador de NQC________________________

    8

    4 para cybermaster, 3 para scout e 32 para spybotics. No mais, quando se utiliza o RCX

    1.0 ou o cybermaster, se uma sub-rotina é chamada, desde múltiplas tarefas, não podem

    ter variáveis locais ou realizar cálculos que necessitem variáveis temporárias. Estas

    importantes restrições fazem com que as sub-rotinas sejam menos atrativas que as

    funções. Portanto, seu uso deveria limitar-se a situações onde seja absolutamente

    necessário economizar no tamanho do código. Segue abaixo a sintaxe de uma sub-

    rotina:

    Nome_da_sub-rotina()

    {

    // corpo da sub-rotina

    }

    2.2.4. Variáveis

    Todas as variáveis em NQC são do mesmo tipo inteiros consígnos de 16 bits.

    As variáveis se declaram usando a palavra reservada int seguido de uma lista de

    nomes de variáveis separadas por vírgulas e terminadas por um ponto e vírgula ( ; ).

    Opcionalmente pode-se especificar um valor inicial para cada variável usando o

    símbolo ( = ) depois do nome da variável. Seguem abaixo alguns exemplos:

    int x; // declara x

    int t,z; // declara t e z

    int a=1,b; // declara a e b, inicia a com o valor 1

    As variáveis globais se declaram no âmbito do programa (fora de qualquer bloco

    de código). Uma vez declaradas podem ser utilizadas dentro de qualquer tarefa, função

    e sub-rotina. Seu âmbito começa com a declaração e termina ao final do programa.

    As variáveis locais podem declarar-se dentro das tarefas, funções e às vezes dentro

    das sub-rotinas. Essas variáveis somente são acessíveis dentro do bloco de código em

    que são definidas. Concretamente, seu âmbito começa com a declaração, e termina ao

    final do bloco de código. No caso das variáveis locais se considera um bloco uma

    instrução composta (um grupo de instruções incluídas entre duas chaves { y } ):

    int x; // x é global

    task main()

    {

    int y; // y é local da tarefa main

    x = y; // ok

    { // começa a instrução composta

    int z; // z declaração local

  • ____________________Guia do programador de NQC________________________

    9

    y = z; // ok

    }

    y = z; // erro aqui não está definida z

    }

    task foo ()

    {

    x = 1; // ok

    y = 2; // erro - y não é global

    }

    Em muitos casos, NQC deve reservar uma ou mais variáveis temporais para o seu

    próprio uso. Em alguns casos utiliza-se uma variável temporal para alocar um valor

    intermediário durante um cálculo. Em outros casos utiliza-se para guardar um valor a

    ser passado à função. Estas variáveis temporais reduzem a reserva de variáveis

    disponíveis para o resto do programa. O NQC tentará ser o mais eficiente possível com

    as variáveis temporais (inclusive reutilizando-as sempre que seja possível).

    O RCX (e outros modelos) proporcionam várias posições de armazenamento e

    podem ser usadas para alocar variáveis em um programa NQC. Existem dois tipos de

    posições de armazenamento: globais e locais. Quando compilam um programa, NQC

    reserva cada variável a um lugar específico de armazenamento. Os programadores

    geralmente podem ignorar os detalhes desta reserva seguindo duas regras básicas:

    Se uma variável necessitar estar em posição global declara-se como

    variável global.

    Se uma variável não necessitar ser global, faz com que seja o mais local

    possível.

    Isto dá ao compilador a máxima flexibilidade ao reservar uma posição de

    armazenamento correta.

    O número de variáveis locais e globais variam segundo o modelo:

    Modelo Global Local

    RCX 32 0

    Cyber Master 32 0

    Scout 10 8

    RCX2 32 16

    Spybotics 32 4

  • ____________________Guia do programador de NQC________________________

    10

    2.2.5. Matrizes

    Os modelos RCX2 e spybotics suportam matrizes (os outros modelos não têm

    suporte apropriado para matrizes em seu firmware). As matrizes declaram-se da mesma

    forma que as variáveis normais, mas com o tamanho das matrizes fechadas entre

    colchetes. O tamanho deve ser uma constante.

    int minha_matriz[3]; // declarar uma matriz de três elementos

    Os elementos de uma matriz identificam-se por sua posição dentro da matriz

    (chamada índice). O primeiro elemento possui um índice 0, o segundo 1, etc. Por

    exemplo:

    minha_matriz[0]=123; // estabelece o primeiro elemento em 123

    minha_matriz[1]= minha_matriz[2];// cópia o terceiro no segundo

    Atualmente existe uma série de limitações no uso de matrizes. É provável que

    essas limitações acabem nas futuras versões de NQC:

    Uma matriz não pode ser argumento de uma função. Todavia pode-se

    passar a uma função um elemento individual da matriz.

    Nem as matrizes nem seus elementos podem utilizar-se com os operadores

    de aumento (++) ou diminuição (--).

    Somente é permitida a utilização normal (=) para os elementos da matriz.

    Não se permitem as utilizações matemáticas (+=).

    Os valores iniciais dos elementos de uma matriz não se podem especificar.

    Necessita de uma reserva explícita dentro do mesmo programa que

    estabeleça o valor de um elemento.

    2.3. Instruções

    O corpo de um bloco de código (tarefa, função ou sub-rotina) compõe-se de

    instruções. As instruções terminam com um ponto e vírgula ( ; ).

    2.3.1. Declaração de variáveis

    A declaração de variáveis, como descrito na sessão anterior, é um tipo de

    instrução. Uma variável declara-se como local (com indicação opcional) quando

    utilizada dentro de um bloco de código. A sintaxe para uma declaração de variável

    é:

  • ____________________Guia do programador de NQC________________________

    11

    Int variáveis;

    Onde variáveis é uma lista de nomes separados por vírgulas com valores iniciais

    opcionais.

    Nome [=expressão]

    As matrizes de variáveis também podem declarar (só para RCX2):

    Int matriz [tamanho]

    2.3.2. Atribuição

    Uma vez declaradas as variáveis pode-se reservar o valor de uma expressão:

    Variável operador_de_atribuição expressão

    Há novos operadores de reserva. O operador mais básico, = , simplesmente

    reserva o valor da expressão para a variável. Os outros operadores modificam de

    alguma forma o valor da variável em um dos modos como se mostra na tabela

    seguinte:

    Operador Ação

    = Atribui a uma variável uma expressão

    += Adiciona a uma variável uma expressão

    -= Resta a uma variável uma expressão

    *= Multiplica uma variável por uma expressão

    /= Divide uma variável por uma expressão

    &= AND bit a bit da expressão e da variável

    |= OR bit a bit da expressão e da variável

    ||= Atribui a uma variável o valor absoluto de uma expressão

    +-= Atribui uma variável o sinal (-1, +1, 0) de uma expressão

    >>= Desloca para a direita a variável em uma quantidade constante

  • ____________________Guia do programador de NQC________________________

    12

    {

    x = 1;

    y = 2;

    }

    Ainda pode não parecer muito significativo, exerce um papel crucial ao construir

    estruturas de controle mais complicadas. Muitas estruturas de controle requerem uma

    instrução simples como corpo. Usando uma instrução composta, a mesma estrutura de

    controle pode ser usada para controlar múltiplas instruções.

    A instrução if demonstra uma condição. Se a condição é verdadeira, executa uma

    instrução (a conseqüência). Uma segunda instrução opcional (a alternativa) é executada

    se a condição é falsa. Continuando, mostram-se as sintaxes possíveis para uma instrução

    if.

    if (condição) conseqüência

    if (condição) conseqüência else alternativa

    Observe que a condição vai ser colocada entre parênteses. Veja os exemplos a

    seguir. No último exemplo utiliza-se uma instrução composta para permitir que se

    executem duas instruções como conseqüências da condição.

    if (x==1) y = 2;

    if (x==1) y = 3; else y = 4;

    if (x==1) {y = 1; z = 2;}

    A instrução while é usada para construir um laço condicional. Avalia-se a

    condição. Se, é verdadeira, executa-se o corpo do laço, a continuação comprova de novo

    a condição. O processo continua até que a condição se torne falsa (o que executa a

    instrução break). A continuação aparece na sintaxe para o laço while:

    while (condição) corpo

    É normal utilizar uma instrução composta como corpo do laço.

    while (x < 10)

    {

    x = x+1;

    y = y*2;

    }

    Uma variante do laço while é o laço do-while. Sua sintaxe é :

    do corpo while (condição)

  • ____________________Guia do programador de NQC________________________

    13

    A diferença entre o laço while e o do-while é que o do-while sempre executa ao

    menos uma vez, enquanto que o laço while pode não executá-lo nunca.

    Outro tipo de laço é o laço for:

    for(instr1 ; condição ; instr2 ;) corpo

    Um laço for sempre executa instr1 logo, checa repetidamente a condição e,

    enquanto é verdadeira, executa o corpo seguido de instr2. O laço for é equivalente a:

    instr1;

    while (condição)

    {

    corpo

    instr2;

    }

    A instrução repeat executa um laço de um número determinado de vezes:

    repeat (expressão) corpo

    A expressão determina quantas vezes se executará o corpo. Observa-se que a

    expressão só se avalia uma vez e o corpo se repete esse número de vezes. Isto é

    diferente nas estruturas while e do-while que avalia a condição em cada laço.

    Uma instrução switch pode utilizar-se para executar um de vários blocos de

    código dependendo do valor de uma expressão. Cada bloco de código vem precedido

    por uma ou mais etiquetas case. Cada case deve ser uma constante única dentro da

    instrução switch. A instrução switch avalia a expressão e a continuação busca uma

    etiqueta case que cumpra a condição. Então executará qualquer instrução que diga case

    até que se encontre uma instrução break ou até que chegue ao final do switch. Também

    pode-se usar uma única etiqueta default que se associará a qualquer valor que não

    apareça na etiqueta case. Tecnicamente uma instrução switch tem a seguinte sintaxe:

    switch (expressão) corpo

    As etiquetas case e default não são instruções em si mesmas, sendo que são

    etiquetas que precedem as instruções. Múltiplas etiquetas podem preceder à mesma

    instrução. Estas etiquetas têm a seguinte sintaxe:

    case expressão_constante:

    default :

  • ____________________Guia do programador de NQC________________________

    14

    Uma típica instrução switch teria este aspecto:

    switch (x)

    {

    case 1 : // faz algo quando x é 1

    break;

    case 2 :

    case 3 : // faz outra coisa quando x é 2 ou 3

    break;

    default : // faz isto quando x não é 1,2 nem 3

    break;

    }

    A instrução goto força o programa a saltar a uma posição determinada. As

    instruções de um programa podem ser marcadas precedendo-as de um identificador e

    dos pontos. Uma instrução goto especifica a etiqueta a que o programa há de saltar. Por

    exemplo, vejamos como implementar um laço que incrementa o valor de uma variável

    utilizando goto:

    Meu_ laço:

    x++;

    goto Meu_ laço;

    A instrução goto deve ser usada com moderação e precaução. Na maioria dos

    casos as estruturas de controle tales como if , while e switch fazem os programas mais

    fáceis de ler e modificar. Têm a precaução de não utilizar nunca uma instrução goto

    para saltar a uma instrução monitor ou acquire ou para sair dela. Isto é assim porque

    monitor e acquire têm um código especial que normalmente é executado na entrada e

    saída, e um goto evitaria este código

    provavelmente provocando um comportamento

    não desejado.

    NQC também define o macro until que supõe uma alternativa prática ao laço

    while. A definição real de until é:

    #define until (c ) while (!( c ))

    Em outras palavras, until continuará fazendo laços até que a condição seja

    verdadeira. Com muita freqüência utiliza-se como uma instrução de corpo vazio:

    until (SENSOR_1 = 1); // espera que se pressione o sensor

  • ____________________Guia do programador de NQC________________________

    15

    2.3.4. Controle de acesso e eventos

    O Scout, RCX2 e Spybotics suportam a monitoração de eventos e o controle de

    acesso. O controle de acesso permite que uma tarefa solicite a posição de um ou mais

    recursos. No NQC o controle de acesso proporciona a instrução acquire, que pode

    apresentar duas formas:

    acquire (recursos) corpo

    acquire (recursos) corpo catch handler

    onde recursos é uma constante que especifica os recursos que há que obter e corpo e

    handler, são instruções. O NQC API define as constantes para os recursos individuais

    que se podem somar para solicitar múltiplos recursos por vez. O comportamento da

    instrução acquire é o seguinte: solicitará a posição dos recursos especificados. Se outra

    tarefa de prioridade superior já possui os recursos, então a solução não será aceita e a

    execução saltará a handler (se existir). Caso contrário o pedido será aceito e o corpo

    começará a ser executado. Enquanto executa-se o corpo, se uma tarefa de prioridade

    igual ou superior solicita alguns dos recursos, a tarefa original perderá sua posição.

    Quando se perde a posição, a execução salta para handler (se existir). Uma vez que o

    corpo está completo devolvem-se os recursos ao sistema (para que possam adquirir

    tarefas de prioridade mais baixa). Se não se especifica um handler, tanto o pedido não é

    aceito como pode sê-lo (com sua conseqüência perdida uma vez executado o corpo) o

    controle passa a instrução que segue a instrução acquire. Por exemplo, o seguinte

    código adquire um recurso 10 segundos, fazendo soar um som não se completa com

    êxito:

    acquire (ACQUIRE_OUT_A)

    {

    Wait (1000);

    }

    catch

    {

    PlaySound (SOUND_UP);

    }

    A monitoração de eventos implementa-se com a instrução monitor, que tem uma

    sintaxe muito similar a instrução acquire:

    monitor (eventos) corpo

    monitor (eventos) corpo handler_list

  • ____________________Guia do programador de NQC________________________

    16

    onde handler_list é um ou mais handlers do tipo:

    catch (catch_events) handler

    O último handler em uma lista de handlers pode omitir a especificação do

    evento:

    catch handler

    Evento é uma constante que determina que eventos devem ser monitorados. Para

    o Scout os eventos estão pré-definidos, de modo que há constantes como

    EVENT_1_PRESSED que podem ser utilizadas como especificação de evento. Com

    RCX2 o significado de cada evento é configurado pelo programador. Existem 16

    eventos (números do 0 ao 15). Para especificar um evento em uma instrução de monitor,

    o número de evento deve converter-se em uma máscara de evento, utilizando a macro

    EVENT_MASK(). As constantes de evento do Scout, as máscaras de evento podem

    somar-se para especificar múltiplos eventos. Podem combinar-se múltiplas máscaras

    por meio do OR bit a bit.

    A instrução monitor executa o corpo enquanto monitoriza os eventos

    especificados. Sucede-se qualquer dos eventos, a execução salta o primeiro handler para

    esse evento (um handler sem nenhuma especificação maneja qualquer evento). Se não

    existe nenhum handler de evento para esse evento, então o controle continua na

    instrução que segue a instrução monitor. O seguinte exemplo espera 10 segundos

    enquanto monitora os eventos 2, 3 e 4 para RCX2:

    monitor (EVENT_MASK (2)| EVENT_MASK (3)| EVENT_MASK (4))

    {

    Wait (1000);

    }

    catch (EVENT_MASK (4))

    {

    PlaySound (SOUND_DOWN); // sucede o evento 4

    }

    catch

    {

    PlaySound (SOUND_UP); // sucede o evento 2 ou 3

    }

    Observe que as instruções acquire e monitor só são suportadas por modelos que

    implementem o controle de acesso e a monitoração de eventos, quer dizer, o Scout e o

    RCX2.

  • ____________________Guia do programador de NQC________________________

    17

    2.3.5. Outras instruções

    Uma chamada da função (ou sub-rotina) é uma instrução como a seguinte:

    Nome(argumentos);

    A lista de argumentos é uma lista de expressões separadas por vírgulas. O

    número e o tipo de argumento que se proporciona, deve coincidir com a definição da

    mesma função.

    As tarefas devem iniciar-se e terminar com as seguintes instruções:

    start nome_de_tarefa;

    stop nome_de_tarefa;

    Dentro dos laços (por exemplo, em um laço while) a instrução break pode ser

    utilizada para sair do laço e a instrução continue pode ser utilizada para saltar a parte

    superior da seguinte interação do laço. A instrução break também pode ser utilizada

    para sair da instrução switch.

    break;

    continue;

    É possível fazer com que uma função finalize antes de chegar ao fimde seu

    código usando a instrução return.

    return;

    Qualquer expressão é também uma instrução legal quando termina em ponto e

    vírgula. É pouco freqüente usar esse tipo de instrução já que então se descartaria no

    valor da expressão. A única exceção mencionada refere-se às expressões que implicam

    nos operadores de acréscimo (++) ou decréscimo (--).

    X++;

    A instrução vazia (só o ponto e vírgula) é também uma instrução legal.

    2.4. Expressões

    As primeiras versões de NQC faziam uma distinção entre expressões e

    condições. Esta diferença elimina-se a partir da versão 2.3: tudo é uma expressão e

    agora operadores condicionais para as expressões. Isto é parecido como utiliza-se em

    C/C++, as operações condicionais.

    Os valores são do tipo mais primitivo de expressões. Formam-se expressões

    mais complicadas a partir de valores, usando vários operadores. A linguagem NQC só

  • ____________________Guia do programador de NQC________________________

    18

    tem incorporado duas classes de valores: constantes numéricas e variáveis. O RCX API

    define outros valores que correspondem a várias características do RCX tais como

    sensores e temporizadores (timers).

    As constantes numéricas no RCX representam-se como inteiros com signo de 16

    bits. Internamente NQC usa matemáticas com signo de 32 bits para a avaliação de

    expressões constantes, logo o reduz a 16 bits quando generaliza o código RCX. As

    constantes numéricas podem ser escritas como decimais (123) ou hexadecimais

    (0xABC). Atualmente, existe muito pouco controle da faixa de valor das constantes, de

    modo que usar um valor maior do que esperado pode ter efeitos não usuais.

    Se predefinem dos valores especiais: true e false. O valor de false é zero,

    enquanto que só se garante que o valor de true não é zero. São válidos os mesmos

    valores para operadores relacionais (

  • ____________________Guia do programador de NQC________________________

    19

    Operador Descrição Associação Restrição Exemplo

    abs () sing ()

    Valor absoluto Sinal de operando

    n/a abs (x) sing (x)

    ++ , -- Incremento, Diminuição Esquerda Só variáveis x++ ou ++x

    - ~ !

    unário menor negação bitwise (unário) negação lógica

    Direita Direita Direita

    Só constantes

    -x ~123 !x

    * / %

    Multiplicação Divisão Modulo

    Esquerda Esquerda Esquerda

    x * y

    + -

    Soma Subtração

    Esquerda Esquerda

    x + y x - y

    >> 4

    < , > =

    Operadores Relacionais Esquerda x < y x > y

    == !=

    Igual a Diferente de

    Esquerda x == 1 x != 1

    & AND bit a bit Esquerda x & y

    ^ XOR bit a bit Esquerda x ^ y

    | OR bit a bit Esquerda x | y

    && AND lógico Esquerda x && y

    || OR lógico Esquerda x || y

    ?: Valor condicional n/a x ==1 ?Y : z

    Pode se usar parêntesis onde seja necessário, para mudar a ordem da avaliação.

    x = 2+3; 4 // atribuir a x o valor 14

    y = (2+3)*4 // atribuir a y o valor 20

    2.4.1. Condicionais

    As condições formam-se, geralmente, comparando duas expressões. Existem

    também duas expressões constantes

    true e false

    que sempre dão como valor de

    avaliação verdadeiro ou falso, respectivamente. Pode-se negar uma condição com o

    operador de negação, ou combinar duas condições com os operadores AND ou OR. A

    tabela seguinte resume os diferentes tipos de condicionais:

  • ____________________Guia do programador de NQC________________________

    20

    Condição Significado

    True Sempre verdadeiro

    False Sempre falso

    Expr Verdade se a expressão não é igual a 0

    Expr1 == Expre2 Verdade se expr1 for igual a expr2

    Expr1 != Expre2 Verdade se expr1 for diferente a expr2

    Expr1 < Expre2 Verdade se expr1 for menor a expr2

    Expr1 Expre2 Verdade se expr1 for maior a expr2

    Expr1 >= Expre2 Verdade se expr1 for maior ou igual a expr2

    ! Condição Negação lógica de uma condição Verdadeiro se a condição for falsa

    Cond1 && Cond2

    AND lógico de duas condições - Verdadeiro se e somente se ambas as condições forem verdadeiras

    Cond1 || Cond2 OR lógico de duas condições - Verdadeiro se e somente se uma condição for verdadeira

    2.5. O pré-processador

    O pré-processador implementa as seguintes diretrizes: #include, #define,

    #ifdef, #ifndef, #if, #elif, #else, #endif, #undef. Sua implementação

    está muito próxima a um pré-processador C standar, de modo que a maior parte das

    coisas que funcionam em um pré-processador C genérico, deveriam ter o efeito

    esperado em NQC. Abaixo aparece uma lista de desvios significativos.

    2.5.1. #include

    O comando #include funciona como era de se esperar, com a ressalva de que o

    nome do arquivo deve ir colocado entre aspas. Não existe noção no sistema de uma rota

    de inclusão, de modo que, fechar um arquivo entre parêntesis angular, está proibido.

    #include foo.nqh // ok

    #include // erro!

    2.5.2. #define

    O comando #define usa-se para uma substituição de macro simples. A

    redefinição de macro é um erro (ao invés que em C onde é um aviso). Os macros

    terminam normalmente pelo final da linha, porém pode escrever a nova linha com ( \ )

    para permitir macros multilinhas.

    #define foo (x) do { bar (x);\

    baz (x); } while (false)

    A diretiva #undef pode-se usar para retirar uma definição de macro.

  • ____________________Guia do programador de NQC________________________

    21

    2.5.3. Compilação condicional

    A compilação condicional funciona de forma parecida ao pré-processador C.

    Podem-se usar as seguintes diretivas de pré-processador.

    #if condição

    #ifdef symbol

    #ifndef symbol

    #else

    #elif condição

    #endif

    As condições nas diretivas #if usam os mesmos operadores e prioridades que em

    C. Suporta-se no operador defined( ).

    2.5.4. Iniciação do programa

    Ao início do programa o pré-processador insere uma chamada a uma função de

    inicialização especial, _init. Esta função, de fato, é parte do RCX API e põe as três

    saídas a plena potência em direção para frente (todavia desconectadas). A função de

    iniciação pode desativar-se usando a diretiva #pragma noinit:

    #pragma noinit //não faz nenhuma iniciação do programa

    A função de iniciação, de fato, pode-se substituir por uma função diferente

    usando a diretiva #pragma init:

    #pragma init função //usar iniciação de usuário

    2.5.5. Armazenamento de reserva

    O compilador NQC atribui, automaticamente, variáveis a posições de

    armazenamento. No entanto, às vezes é necessário impedir que o compilador use certas

    posições de armazenamento. Isto pode-se fazer por meio da diretiva:

    #pragma reserve:

    #pragma reserve início

    #pragma reserve início fim

    Esta diretiva faz com que o compilador ignore uma ou mais posições de

    armazenamento, durante a atribuição de variáveis. Início e fim devem ser números que

    se refiram as posições de armazenamento válidas. Só se proporciona um início, então se

    reserva uma única posição. Se especificam ambos, início e fim então, se reserva a escala

    de posições de principio a fim (inclusive). O uso mais comum desta diretiva é para

    reservar as posições 0, 1 e/ou 2 ao usar contadores para RCX2. Isto é porque os

  • ____________________Guia do programador de NQC________________________

    22

    contadores de RCX2 se sobrepõem com as posições de armazenamento 0, 1 e 2. Por

    exemplo, se fossem utilizar os três contadores:

    #pragma reserve 0 1 2

    3. NQC API

    O NQC API define um grupo de constantes, funções, valores e macros que

    proporcionam acesso a várias capacidades do modelo como sensores, saídas,

    temporizadores e comunicações. Algumas características só se encontram em certos

    modelos. Sempre que seja necessário, o título da seção indica a que o modelo se aplica.

    O RCX2 reúne todas as características do RCX, de modo que se faz referência ao RCX,

    então essa característica funciona com o firmware original e com o firmware 2.0. Se faz

    referência ao RCX2 a característica que só se aplica ao firmware 2.0. CyberMaster,

    Scout e Spybotics se indicam como CM, Scout e Spy, respectivamente.

    O API consiste em funções, valores e constantes. Uma função é algo que pode

    ser também denominada instrução. Tipicamente, empreende alguma ação ou configura

    algum argumento. Os valores representam algum argumento ou quantidade, e podem ser

    usados em expressões. As constantes são nomes simbólicos para valores que têm

    significado especial para o modelo. A princípio, usa-se um grupo de constantes junto

    com uma função. Por exemplo, a função PlaySound utiliza um simples argumento que

    determina que som tocará. As constantes, tais como SOUND_UP, definem-se para cada

    som.

    3.1. Sensores

    Existem três sensores, que se enumeram internamente 0, 1 e 2. Isto poderia dar

    confusão já que no RCX está etiquetado externamente como 1, 2 e 3. Para minimizar

    esta confusão, foi definido os nomes dos sensores SENSOR_1, SENSOR_2 e

    SENSOR_3. Esses nomes de sensores podem ser usados em qualquer função, que

    requeira um sensor como argumento. No mais, podem-se usar os nomes sempre que um

    programa deseje ler o valor atual de um sensor:

    x = SENSOR_1; // lê o sensor y armazena o valor em x

    3.1.1. Tipos e modos RCX, CyberMaster

    As portas de sensores no RCX têm capacidade de suportar uma grande variedade

    de sensores (outros modelos não suportam tipos de sensor configuráveis). É função do

    programa dizer ao RCX que classe de sensor está conectada em cada porta. Se pode

  • ____________________Guia do programador de NQC________________________

    23

    configurar o tipo do sensor por meio de SetSensorType. Existem quatro tipos de

    sensores e cada qual corresponde a um sensor específico de LEGO. Pode-se usar um

    quinto tipo (SENSOR_TYPE_NONE) para ler os valores puros dos sensores genéricos

    passivos. Em geral, um programa deveria configurar o tipo para que encaixe com o

    sensor real. Se uma porta de sensor se configurar com o tipo incorreto, o RCX pode não

    ser capaz de ler corretamente.

    Tipo de Sensor Significado

    SENSOR_TYPE_NONE Sensor passivo - Genérico

    SENSOR_TYPE_TOUCH Sensor de toque

    SENSOR_TYPE_TEMPERATURE Sensor de temperatura

    SENSOR_TYPE_LIGHT Sensor de luz

    SENSOR_TYPE_ROTATION Sensor de rotação

    O RCX, CyberMaster e Spybotics permitem que se configure um sensor em

    modos diferentes. O modo de sensor determina como se processa o valor puro de um

    sensor. Alguns modos só têm sentido para certos tipos de sensores, por exemplo

    SENSOR_MODE_ROTATION só é útil com sensores de rotação. O modo de sensor

    pode estabelecer por meio de SetSensorMode. A continuação mostra os possíveis

    modos. Adverte-se que, já que CyberMaster não suporta sensores de rotação ou de

    temperatura, os últimos três modos se restringem somente ao RCX. Spybotics é todavia

    mais restrito e, somente permite os modos raw, booleano e porcentual.

    Modo do Sensor Significado

    SENSOR_MODE_RAW Valor puro de 0 a 1023

    SENSOR_MODE_BOOL Valor booleano (0 ou 1)

    SENSOR_MODE_EDGE Conta números de transições booleanas

    SENSOR_MODE_PULSE Conta números de períodos booleanos

    SENSOR_MODE_PERCENT Valor de 0 a 100

    SENSOR_MODE_FAHRENHEIT Graus F - Somente RCX

    SENSOR_MODE_CELSIUS Graus C - Somente RCX

    SENSOR_MODE_ROTATION Rotação (16 ticks por revolução) - Somente RCX

    Ao usar o RCX é normal pôr o tipo e o modo ao mesmo tempo. A função

    SetSensor faz este processo um pouco mais fácil ao proporcionar uma única função

    que chama e estabelece um conjunto de combinações tipo/modo padrão.

  • ____________________Guia do programador de NQC________________________

    24

    Configuração do Sensor Tipo Modo

    SENSOR_TOUCH SENSOR_TYPE_TOUCH SENSOR_MODE_BOOL

    SENSOR_LIGHT SENSOR_TYPE_LIGHT SENSOR_MODE_PERCENT

    SENSOR_ROTATION SENSOR_TYPE_ROTATION SENSOR_MODE_ROTATION

    SENSOR_CELSIUS SENSOR_TYPE_TEMPERATURE SENSOR_MODE_CELSIUS

    SENSOR_FAHRENHEIT SENSOR_TYPE_TEMPERATURE SENSOR_MODE_FAHRENHEIT

    SENSOR_PULSE SENSOR_TYPE_TOUCH SENSOR_MODE_PULSE

    SENSOR_EDGE SENSOR_TYPE_TOUCH SENSOR_MODE_EDGE

    O RCX proporciona uma conversão booleana para todos os sensores

    não só

    para os sensores de contato. Esta conversão booleana baseia-se, normalmente, em

    entradas préestablecidos para o valor puro. Um valor baixo (menor de 460) é um

    valor booleano de 1. Um valor alto (maior de 562) é um valor booleano de 0. Esta

    conversão pode modificar: ao chamar SetSensorMode pode adicionar um valor de

    entrada entre 0 e 31. Se o valor do sensor mudar mais que o valor de entrada durante

    certo tempo (3 milisegundos), então troca o estado booleano do sensor. Isto permite que

    o estado booleano reflita mudanças rápidas no valor puro. Um aumento rápido ocasiona

    um valor booleano de 0, uma descida rápida em um valor booleano de 1. Inclusive

    quando um sensor se configura para outro modo (por exemplo

    SENSOR_MODE_PERCENT), se leva a cabo a conversão booleana.

    SetSensor (sensor, configuração) Função RCX

    Estabelece o tipo e modo de um sensor dado em uma configuração específica,

    que deve ser uma constante especial contendo o tipo e o modo da informação.

    SetSensor (SENSOR_1, SENSOR_TOUCH);

    SetSensorType (sensor, tipo) Função RCX

    Estabelece um tipo de sensor, que deve ser uma das constantes de tipo de sensor

    pré-definidos.

    SetSensorType(SENSOR_1, SENSOR_TYPE_TOUCH);

    SetSensorMode (sensor, modo) Função - RCX, CM, Spy

    Estabelece um modo de sensor, que deve ser uma das constantes de modo de

    sensor pré-definidos. Pode-se adicionar, se desejar, (somente ao modo RCX ) um

    argumento de entrada para converção booleana.

    SetSensorMode(SENSOR_1, SENSOR_MODE_RAW); // modo puro

    SetSensorMode(SENSOR_1, SENSOR_MODE_RAW+10); // entrada 10

  • ____________________Guia do programador de NQC________________________

    25

    ClearSensor(sensor) Função Todas

    Apaga o valor de um sensor

    só afeta aos sensores que se configuram para

    medir uma quantidade acumulativa, tal como a rotação uma recontagem de pulso.

    ClearSensor(SENSOR_1);

    3.1.2. Informação do sensor

    Existe um número de valores que se pode inspecionar para cada sensor. Para

    todos esses valores deve-se especificar o sensor por seu número de sensor (0, 1 ou 2), e

    não com a constante correspondente (ex. SENSOR_1).

    SensorValue(n) Valor Todos

    Devolve a leitura processada do sensor para o sensor n, onde n é 0, 1 ou 2. Este é

    o mesmo valor que devolve os nomes de sensor (ex. SENSOR_1).

    x = SensorValue(0); // lê o sensor 1

    SensorType(n) Valor RCX, CM, Scout

    Devolve o tipo configurado do sensor n, que deve ser 0, 1 ou 2. Somente tem

    tipos configuráveis de sensor RCX, outros suportes devolvem o tipo pré-configurado de

    sensor.

    x = SensorType(0);

    SensorMode(n) Valor RCX, CyberMaster, Spy

    Devolve o modo de sensor em uso para o sensor n, que deve ser 0, 1 ou 2.

    x = SensorMode(0);

    SensorValueBool(n) Valor RCX

    Devolve o valor booleano do sensor n, que deve ser 0, 1 ou 2. A conversão

    booleano se faz baseando-se, ou bem em limites preestabelecidos, ou em um argumento

    slope especificado por meio de SetSensorMode.

    x = SensorValueBool(0);

    SensorValueRaw(n) Valor RCX, Scout, Spy

    Devolve o valor puro do sensor n, que deve ser 0, 1 ou 2. Os valores puros

    variam entre 0 e 1023.

    x = SensorValueRaw(0);

  • ____________________Guia do programador de NQC________________________

    26

    3.1.3. Sensor de luz do Scout Scout

    No Scout, SENSOR_3 refere-se ao sensor de luz que vem incorporado. A leitura

    do valor do sensor de luz (com SENSOR_3) devolve um dos três níveis: 0 (escuro), 1

    (normal) o 2 (brilhante). Pode-se ler o valor puro do sensor com

    SensorValueRaw(SENSOR_3), mas tem que levar em conta que uma luz mais brilhante,

    ocasiona um valor puro mais baixo. A conversão do valor puro do sensor (entre 0 e

    1023) a um dos três níveis depende de três argumentos: limite superior, limite inferior e

    delay. O limite inferior é o valor puro menor (mais brilhante) que ainda se considera

    normal. Os valores abaixo do limite mais baixo se consideram brilhantes. O limite

    superior é o maior valor puro (mais escuro) que se considera normal. Os valores perto

    deste limite se consideram escuros.

    Pode-se usar o delay para impedir que mude o nível, quando o valor puro chegue

    perto de um dos limites. Isto se consegue, fazendo com que seja um pouco mais difícil

    abandonar os estados escuros e brilhantes que entram neles. Especificamente, o limite

    para mover-se de normal a brilhante é um pouco mais baixo que o limite para voltar de

    brilhante a normal. A diferença entre estes dois limites é a margem do delay. O mesmo

    acontece para a transição entre normal e escuro.

    SetSensorLowerLimit (valor) Função Scout

    Estabelece o valor inferior da luz do sensor. O valor pode ser uma expressão.

    SetSensorLowerLimit (100);

    SetSensorUpperLimit (valor) Função Scout

    Estabelece o valor superior da luz do sensor. O valor pode ser uma expressão.

    SetSensorUpperLimit (900);

    SetSensorHysteresis (valor) Função Scout

    Estabelece o delay do sensor de luz. O valor pode ser uma expressão.

    SetSensorHysteresis (20);

    CalibrateSensor ( ) Função - Scout

    Lê o valor do sensor de luz, depois estabelece os limites superior e inferior em

    12,5% por cima o por baixo da leitura atual, e estabelece um delay de 3.12% do valor da

    leitura.

    CalibrateSensor();

  • ____________________Guia do programador de NQC________________________

    27

    3.1.4. Sensores do Spybotics Spy

    Spybotics utiliza sensores embutidos, em lugar de sensores conectados

    externamente. O sensor de contato que se encontra na parte frontal do tijolo Spybotics é

    o SENSOR_1. Está normalmente configurado no modo percentual, seu valor é 0 quando

    não está pressionado e 100 quando está. SENSOR_2 é o sensor de luz (o conector na

    parte traseira do tijolo que se usa para se comunicar com o computador). Está

    normalmente configurado no modo percentual, valores altos indicam luz brilhante.

    3.2. Saídas

    3.2.1. Funções básicas

    Todas as funções que utilizam saídas, estabelecem, como primeiro argumento

    um conjunto de saídas. Este valor tem que ser uma constante. Os nomes OUT_A,

    OUT_B, e OUT_C usam-se para identificar as três saídas. Várias saídas podem ser

    combinadas encadeando saídas individuais. Por exemplo, usa-se OUT_A+OUT_B para

    especificar as saídas A e B, em uma só instrução. O valor das saídas tem que ser sempre

    uma constante (não pode ser uma variável).

    Cada saída tem três atributos: modo, direção e potência. Modo, pode ser

    configurado por meio de SetOutput(saída, modo). O argumento modo deve ser uma das

    seguintes constantes:

    Modo Significado

    OUT_OFF A saída está desligada (O motor não pode girar)

    OUT_ON A saída está ligada (O motor pode girar)

    OUT_FLOAT O motor seguirá girando até parar por si só

    Os outros dois atributos, direção e potência, podem ser configurados em

    qualquer momento, mas só têm efeito se a saída está ligada. A direção é configurada

    mediante o comando SetDirection(saída,direção). O argumento direção deve ser uma

    das seguintes constantes:

    Direção Significado

    OUT_FWD O motor gira para frente

    OUT_REV O motor gira para trás

    OUT_TOGGLE O motor inverte o sentido de giro

    A potência pode ser configurada entre 0 (mínima) e 7 (máxima). Os valores

    OUT_LOW, OUT_HALF e OUT_FULL estão definidos para serem utilizados na

    configuração do argumento potência. A potência pode ser estabelecida mediante a

  • ____________________Guia do programador de NQC________________________

    28

    função SetPower(saída,potencia). Por padrão, os três motores estão configurados a

    máxima potência e giro para frente quando o programa inicia. Contudo, o RCX neste

    momento está parado.

    SetOutput(saídas, modo) Função Todos

    Estabelece a saída no modo especificado. Saída é um ou mais dos valores

    OUT_A, OUT_B, e OUT_C. O modo tem que ser OUT_ON, OUT_OFF, ou OUT_FLOAT.

    SetOutput(OUT_A + OUT_B, OUT_ON); // Estabelece A e B ligado

    SetDirection(saídas, direção) Função - Todos

    Estabelece a saída na direção especificada. Saída é um ou mais dos valores

    OUT_A, OUT_B, e OUT_C. A direção tem que ser OUT_FWD, OUT_REV, ou

    OUT_TOGGLE.

    SetDirection(OUT_A, OUT_REV); // Faz girar A para trás

    SetPower(saídas , potência) Função - Todos

    Estabelece a potência do motor especificado. A potência pode ser uma

    expressão, cujo resultado deve ser um valor entre 0 e 7. As constantes OUT_LOW,

    OUT_HALF, ou OUT_FULL também podem ser usadas.

    SetPower(OUT_A, OUT_FULL); // A a máxima potência

    SetPower(OUT_B, x);

    OutputStatus(n) Valor - Todos

    Devolve o estado do motor n. Tendo em conta que n deve ser 0, 1 ou 2

    não

    OUT_A, OUT_B, ou OUT_C.

    x = OutputStatus(0); // Estado de OUT_A

    3.2.2. Outras funções

    Dado que o controle das saídas é uma característica de uso freqüênte dentro do

    programa, se dispõe de outras funções que fazem com que se trabalhar com saídas seja

    mais fácil. Deve levar-se em conta que estes comandos não adicionam nenhuma nova

    funcionalidade aos comandos SetOutput e SetDirection. Só são interessantes para fazer

    o programa mais conciso.

  • ____________________Guia do programador de NQC________________________

    29

    On(saídas) Função - Todos

    Estabelece as saídas especificadas como ligadas. Saída é um ou mais dos valores

    OUT_A, OUT_B, e OUT_C.

    On(OUT_A + OUT_C); // Liga as saídas A e C

    Off(saídas) Função - Todos

    Estabelece as saídas especificadas como apagadas. Saída é um ou mais dos

    valores OUT_A, OUT_B, e OUT_C.

    Off(OUT_A); // Apaga a saída A

    Float(saídas) Função - Todos

    Estabelece as saídas especificadas como float. Saída é um ou mais dos valores

    OUT_A, OUT_B, e OUT_C.

    Float(OUT_A); // Detém a saída A sem freá-la

    Fwd(saídas) Função Todos

    Estabelece o sentido de giro das saídas especificadas como para frente. Saída é

    um ou mais dos valores OUT_A, OUT_B, e OUT_C.

    Fwd(OUT_A);

    Rev(saídas) Função - Todos

    Estabelece o sentido de giro das saídas especificadas como retrocesso. Saída é

    um ou mais dos valores OUT_A, OUT_B, e OUT_C.

    Rev(OUT_A);

    Toggle(saídas) Função - Todos

    Inverte o sentido de giro das saídas especificadas. Saída é um ou mais dos

    valores OUT_A, OUT_B, e OUT_C.

    Toggle(OUT_A);

    OnFwd(saídas) Função - Todos

    Estabelece o sentido de giro das saídas especificadas como para frente e as põe

    em marcha. Saída é um ou mais dos valores OUT_A, OUT_B, e OUT_C.

    OnFwd(OUT_A);

  • ____________________Guia do programador de NQC________________________

    30

    OnRev(saídas) Função - Todos

    Estabelece o sentido de giro das saídas especificadas como retrocesso e as põe

    em marcha. Saída é um ou mais dos valores OUT_A, OUT_B, e OUT_C.

    OnRev(OUT_A);

    OnFor(saídas, tempo) Função - Todos

    Põe em marcha as saídas especificadas por um determinado tempo e a

    continuação as detém. Saída é um ou mais dos valores OUT_A, OUT_B, e OUT_C.

    Tempo se mede em incrementos de 10ms (one second = 100) e pode ser uma

    expressão.

    OnFor(OUT_A, x);

    3.2.3. Controle Global RCX2, Scout

    SetGlobalOutput(saídas, modo) Função - RCX2, Scout, Spy

    Desativa ou volta a ativar as saídas dependendo do argumento modo. Se modo é

    OUT_OFF, então as saídas se apagaram e se desativaram. Enquanto estão desativadas

    qualquer chamada SetOutput() (incluindo funções tais como On()) será ignorada. Se, se

    utiliza o modo OUT_FLOAT, às saídas estarão estabelecidas no modo float antes de

    desativá-las. As saídas podem voltar a ser ativadas chamando SetGlobalOutput() e

    modo OUT_ON. Deve levar-se em conta que ativar uma saída não a liga

    imediatamente, só permite posteriores chamadas a SetOutput().

    SetGlobalOutput(OUT_A, OUT_OFF); //desativa a saída A

    SetGlobalOutput(OUT_A, OUT_ON); //ativa a saída A

    SetGlobalDirection(saídas, direção) Função - RCX2, Scout, Spy

    Inverte ou reestabelece a direção das saídas. O argumento direção deve ser

    OUT_FWD, OUT_REV ou OUT_TOGGLE. Se SetGlobalDirection é OUT_FWD o

    comportamento da saída é o normal. Se SetGlobalDirection é OUT_REV o

    valor de saída de direção será o oposto do que se atribui pelas funções básicas. Se

    SetGlobalDirection é OUT_TOGGLE este mudará entre o comportamento

    normal e o comportamento oposto.

    SetGlobalDirection(OUT_A, OUT_REV); //direção oposta

    SetGlobalDirection(OUT_A, OUT_FWD); //direção normal

  • ____________________Guia do programador de NQC________________________

    31

    SetMaxPower(saídas, potência) Função - RCX2, Scout, Spy

    Estabelece o valor máximo de potência permitida para as saídas. Potência pode

    ser uma variável, mas deve ter um valor entre OUT_LOW e OUT_FULL.

    SetMaxPower(OUT_A, OUT_HALF);

    GlobalOutputStatus(n) Função RCX2, Scout, Spy

    Devolve a configuração global da saída do motor n. Deve levar-se em conta que

    n tem que ser 0, 1 ou 2 não OUT_A, OUT_B ou OUT_C.

    X = GlobalOutputStatus(0); //Estado global de OUT_A

    3.2.4. Saídas de Spybotics

    Spybotics tem dois motores internos. OUT_A refere-se ao motor direito e

    OUT_B ao esquerdo. OUT_C enviará ordens VLL por meio do LED traseiro (o que se

    utiliza para as comunicações com o ordenador). Isto permite a um dispositivo VLL,

    como o Micro_Scout, ser utilizado como terceiro motor do Spybotics. O mesmo LED

    pode ser controlado utilizando as funções SendVLL() e SetLight().

    3.3. Som

    PlaySound(som) Função - Todos

    Executa um dos 6 sons pré-determinados do RCX. O argumento som tem que

    ser uma constante (exceto em Spybotics, que permite utilizar uma variável).

    As seguintes constantes estão pré-definidas para serem usadas com a função

    PlaySound(): SOUND_CLICK, SOUND_DOUBLE_BEEP, SOUND_DOWN, SOUND_UP,

    SOUND_LOW_BEEP, SOUND_FAST_UP.

    PlaySound(SOUND_CLICK);

    PlayTone(freqüência, duração) Função - Todos

    Executa um só tom da freqüência e duração específica. O valor de freqüência é

    em hertz e pode ser uma variável para RCX2, Scout e Spybotics, mas tem que ser uma

    constante para RCX e CyberMaster. O valor duração é em centésimos de segundo e tem

    que ser constante.

    PlayTone(440,50); //Executa um La de meio segundo

  • ____________________Guia do programador de NQC________________________

    32

    MuteSound() Função - RCX2, Scout, Spy

    Faz com que se deixe de executar todos os sons e tons.

    MuteSound();

    UnmuteSound() Função - RCX2, Scout, Spy

    Devolve o comportamento normal de sons e tons.

    UnmuteSound();

    ClearSound() Função - RCX2, Spy

    Elimina todos os sons pendentes de serem executados no buffer.

    ClearSound();

    SelectSounds(grupo) Função - Scout

    Seleciona que grupo de sons do sistema devem ser usados. O grupo deve ser

    uma constante.

    SelectSound();

    3.4. Display LCD RCX

    O RCX tem 7 modos diferentes de display como se mostra abaixo. O pré-

    determinado do RCX é DYSPLAY_WATCH.

    Modo Conteúdo do LCD

    DISPLAY_WATCH Mostra o relógio do sistema

    DISPLAY_SENSOR_1 Mostra o valor do sensor 1

    DISPLAY_SENSOR_2 Mostra o valor do sensor 2

    DISPLAY_SENSOR_3 Mostra o valor do sensor 3

    DISPLAY_OUT_A Mostra a configuração da saída A

    DISPLAY_OUT_B Mostra a configuração da saída B

    DISPLAY_OUT_C Mostra a configuração da saída C

    O RCX2 atribui um oitavo modo: DISPLAY_USER. Este modo lê,

    continuamente, um valor fonte e o mostra no visor. Pode mostrar um ponto decimal em

    qualquer posição entre os valores. Isto permite emular o trabalho, com frações, ainda

    que todos os valores estejam armazenados como inteiros. Por exemplo, a seguinte

    função irá mostrar o valor 1234, mostrando duas cifras depois do ponto decimal,

    fazendo com que apareça 12.34 no LCD.

    SetUserDisplay(1234,2);

    O seguinte programa ilustra a atualização do display:

  • ____________________Guia do programador de NQC________________________

    33

    task main()

    {

    ClearTimer(0);

    SetUserDisplay(Timer(0),0);

    Until(false);

    }

    Dado que o modo SetUserDysplay atualiza constantemente o LCD, existem

    algumas restrições no código fonte. Se, se usa uma variável, esta deve ser atribuída a

    uma variável global. A melhor maneira para assegurar que é assim, é declará-la como

    variável global. Também podem produzir-se outros efeitos estranhos. Por exemplo, se

    está mostrando uma variável e se executa um cálculo em que o resultado é a variável, é

    possível que o display mostre alguns resultados intermediários:

    int x;

    task main()

    {

    SetUserDisplay(x,0);

    while(true)

    {

    // O display pode mostrar durante um instante 1

    x = 1 + Timer(0);

    }

    }

    SelectDisplay(modo) Função - RCX

    Seleciona um modo de display.

    SelectDisplay(DISPLAY_SENSOR_1); // mostra o sensor 1

    SetUserDisplay(valor,precisão) Função - RCX2

    Estabelece que o display LCD mostre continuamente um valor especificado.

    Precisão específica o número de dígitos à direita do ponto decimal. Uma

    precisão de 0 não mostra ponto decimal.

    SetUserDisplay(Timer(0),0); // mostra o temporizador 0

    3.5. Comunicações

    3.5.1. Mensagens RCX, Scout

    O RCX e o Scout podem enviar e receber mensagens, simples, utilizando os

    infravermelhos. Uma mensagem pode ter um valor desde 0 até 255, mas não se

  • ____________________Guia do programador de NQC________________________

    34

    recomenda utilizar a mensagem 0. A última mensagem recebida é guardada e, pode-se

    acessá-la mediante Message(). Se não foi recebida nenhuma mensagem, Message()

    devolverá o valor 0. Deve-se levar em conta, que devido a natureza da comunicação

    mediante infravermelhos, não poderão receber mensagens enquanto uma mensagem

    estiver sendo transmitida.

    ClearMessage(valor, precisão) Função - RCX, Scout

    Apaga o buffer de mensagens. Isto facilita a detecção de uma mensagem

    recebida, já que então o programa pode esperar que a Message() não seja zero:

    ClearMessage(); // Apaga as mensagens recebidas

    until(Message() > 0); //Espera a mensagem seguinte

    SendMessage(mensagem) Função - RCX, Scout

    Envia uma mensagem por infravermelhos. Mensagem pode ser uma expressão,

    mas o RCX só pode enviar mensagens com um valor entre 0 e 255, portanto só os 8 bits

    menores do argumento serão usados.

    SendMessage(3); // envia mensagem 3

    SendMessage(259); // outra maneira de enviar a mensagem 3

    SetTxPower(potência) Função RCX, Scout

    Estabelece a potência para a transmissão por infravermelhos. Potência tem que

    ser uma destas constantes: TX_POWER_LO ou TX_POWER_HI

    3.5.2. Série RCX2, Scout

    O RCX2 pode transmitir dados série, pela porta de infravermelhos. Antes de

    enviar dados, a configuração da comunicação e dos pacotes têm que ser especificada.

    Então, para cada transmissão, os dados devem ser colocados no buffer de transmissão e

    então, usar a função SendSerial() para enviá-los. A configuração da comunicação é

    establecida mediante SetSerialComm()e, determina como são enviados os bits mediante

    a porta de infravermelho. Os valores possíveis se mostram abaixo:

    Opção Efeito

    SERIAL_COMM_DEFAULT Configuração prédeterminada

    SERIAL_COMM_4800 4800 Baud

    SERIAL_COMM_DUTY25 25% Duty cycle

    SERIAL_COMM_76KHZ 76 khz carrier

  • ____________________Guia do programador de NQC________________________

    35

    Por definição, está configurado enviar dados a 2400 baud usando um duty cycle

    de 50% em um carrier de 38 kHz. Para especificar opções múltiplas (como a 4800 baud

    com um duty cycle de 25%), combinam-se as opções individuais utilizando OR bit a bit

    (SERIAL_COMM_4800 | SERIAL_COMM_DUTY25). A configuração dos pacotes

    estabelecem-se com SetSerialPacket e controla a maneira como se monta os bytes em

    pacotes. Os valores possíveis se mostram abaixo:

    Opção Efeito

    SERIAL_PACKET_DEFAULT Sem formato de pacotes , somente os bits de dados

    SERIAL_PACKET_PREAMBLE Envia um preâmbulo do pacote

    SERIAL_PACKET_NEGATED Envia cada byte com seu complemento

    SERIAL_PACKET_CHECKSUM Inclui um checksum para cada pacote

    SERIAL_PACKET_RCX Formato padrão do RCX (preâmbulo dados negados e checksum)

    Deve-se levar em conta que os pacotes negados sempre incluem um checksum,

    por tanto a opção SERIAL_PACKET_CHECKSUM só tem significado quando

    SERIAL_PACKET_NEGATED não tiver sido especificado. Igualmente, o preâmbulo

    negados e checksum estão implícitos no SERIAL_PACKET_RCX. O buffer de

    transmissão pode guardar até 16 bytes de dados. Por exemplo, o seguinte código envia

    dois bytes (0x12 y 0x34) à porta série:

    SetSerialComm(SERIAL_COMM_DEFAULT);

    SetSerialPacket(SERIAL_PACKET_DEFAULT);

    SetSerialData(0,0x12);

    SetSerialData(1,0x34);

    SendSerial(0,2);

    SetSerialComm(configuração) Função - RCX2

    Estabelece a configuração da comunicação que determinando que modos são

    enviados os bits pelos infravermelhos.

    SetSerialComm(SERIAL_COMM_DEFAULT);

    SetSerialPacket(configuração) Funcão - RCX2

    Estabelece a configuração dos pacotes que determinando de que modos os bytes

    são montados em pacotes.

    SetSerialPacket(SERIAL_PACKET_DEFAULT);

    SetSerialData(n,valor) Função - RCX2

  • ____________________Guia do programador de NQC________________________

    36

    Coloca um byte de dados no buffer de transmissão. n é o índice do byte a

    establecer (0-15), e o valor pode ser uma expressão

    SetSerialData(3,x); // estabelece o byte 3 em x

    SerialData(n) Funcão - RCX2

    Devolve o valor do byte do buffer de transmissão (não os dados recebidos). N

    tem que ser uma constante entre 0 e 15.

    X = SerialData(7);// lê o byte #7

    SendSerial(começo, contador) Função - RCX2

    Utiliza conteúdo do buffer de transmissão para construir um pacote e enviá-lo

    por infravermelhos (de acordo com a configuração atual de pacotes e comunicação).

    Começo e contador são constantes que especificam o primeiro byte e o número de bytes

    dentro do buffer que se devem enviar

    SendSerial(0,2);// envia os dois primeiros bytes do buffer

    3.5.3. VLL (Link de luz visível) Scout

    SendVLL(valor) Função Scout, Spy

    Envia um comando VLL que pode ser usado para comunicar-se com o

    MicroScout ou o CodePilot. Os comandos específicos VLL estão descritos no SDK do

    Scout.

    SendVLL(4); // Envia o comando VLL #4

    3.6. Temporizadores

    Os diferentes modelos oferecem temporizadores, independentes, com uma

    resolução de 100 ms (10 ticks por segundo). O Scout dispõe de 3 temporizadores,

    enquanto o RCX, o Cybermaster e o Spybotics de 4. Os temporizadores vão desde o tic

    0 até o tic 32767 (ao redor de 55 minutos). O valor do temporizador pode ser lido

    usando Timer(n), onde n é uma constante que determina que temporizador usar (0-2

    para o Scout, 0-3 para o resto). O RCX2 e o Spybotics possuem a característica de ler o

    mesmo temporizador com maior resolução usando FastTimer(n), que devolve o valor

    do temporizador com uma resolução de 10 ms (100 ticks por segundo).

  • ____________________Guia do programador de NQC________________________

    37

    ClearTimer(n) Função - Todos

    Põe a zero o temporizador especificado.

    ClearTimer(0);

    Timer(n) Função - Todos

    Devolve o valor atual do temporizador especificado (com uma resolução de 100

    ms).

    x = Timer(0);

    SetTimer(n,valor) Função RCX2, Spy

    Configura o temporizador com um valor especificado (que pode ser uma

    expressão).

    SetTimer(0,x);

    FastTimer(n) Função - RCX2, Spy

    Devolve o valor atual do temporizador especificado com uma resolução de 10

    ms.

    x = FastTimer(0);

    3.7. Contadores RCX2, Scout, Spy

    Os contadores são como variáveis simples que podem ser incrementadas,

    decrescidas, e apagadas. O Scout dispõe de dois contadores (0 e 1), enquanto que o

    RCX2 e Spybotics dispõem de três (0, 1, 2). No caso do RCX2, estes contadores se

    sobrepõem com direções de armazenagem global 0-2, portanto, vão ser usadas como

    contadores haverá de ser reservadas com #pragma para evitar que NQC as utilize como

    uma variável comum. Por exemplo, se se deseja utilizar o contador 1:

    #pragma reserve 1

    ClearCounter(n) Função - RCX2, Scout, Spy

    Põe a zero o contador n. n tem que ser 0 ou 1 para o Scout, 0-2 para o RCX2 e

    Spybotics.

    Clear Counter(1);

    IncCounter(n) Função - RCX2, Scout, Spy

    Incrementa o contador n em 1. n tem que ser 0 ou 1 para o Scout, 0-2 para o

    RCX2 e Spybotics.

  • ____________________Guia do programador de NQC________________________

    38

    IncCounter(1);

    DecCounter(n) Função - RCX2, Scout, Spy

    Decrescida o contador n em 1. n tem que ser 0 ou 1 para o Scout, 0-2 para o

    RCX2 e Spybotics.

    DecCounter(1);

    Counter(n) Função - RCX2, Scout, Spy

    Devolve o valor do contador n. n tem que ser 0 ou 1 para o Scout, 0-2 para o

    RCX2 e Spybotics.

    x = Counter(1);

    3.8. Controle de Acesso RCX2, Scout, Spy

    O controle de acesso é implementado, principalmente, por meio das declarações

    acquire. A função SetPriority pode ser usada para estabelecer a prioridade de uma

    função, e as seguintes constantes podem ser usadas para especificar os recursos em uma

    declaração acquire. Deve levar-se em conta que a definição dos recursos só está

    disponível no RCX2.

    Constante Recurso

    ACQUIRE_OUT_A

    ACQUIRE_OUT_B

    ACQUIRE_OUT_C

    Saídas

    ACQUIRE_OUT_SOUND Som

    ACQUIRE_LED LEDs (Somente spybotics)

    ACQUIRE_USER_1

    ACQUIRE_USER_2

    ACQUIRE_USER_3

    ACQUIRE_USER_4

    Definidas pelo usuário ( Somente em RCX2)

    SetPriority(p) Função - RCX2, Scout, Spy

    Estabelece a prioridade de uma função a p, que deve ser constante. RCX2

    suporta prioridades 0-255, enquanto o Scout suporta prioridades 0-7. Deve levar-se em

    conta que para números menores, prioridade maior.

    SetPriority(1);

    3.9. Eventos RCX2, Scout

    Ainda que o RCX2, Scout e Spybotics comportem um mecanismo comum de

    eventos, o RCX2 e Spybotics dispõem de 16 eventos, completamente, configuráveis,

  • ____________________Guia do programador de NQC________________________

    39

    enquanto que o Scout dispõe de 15 eventos pré-definidos. As únicas funções comuns

    nestes modelos são os comandos para inspecionar e forçar eventos.

    ActiveEvents(tarefa) Valor - RCX2, Scout, Spy

    Devolve os eventos que foram produzidos em uma tarefa dada.

    x = ActiveEvents(0);

    CurrentEvents() Valor - RCX2, Scout, Spy

    Devolve os eventos que foram produzidos na tarefa atual.

    x = CurrentEvents();

    Event(eventos) Valor - RCX2, Scout, Spy

    Ativa, manualmente, um evento. Isto pode ser útil para provar o tratamento de

    eventos de um programa ou, em outros casos, para simular um evento baseado em

    outros argumentos. Deve-se levar em conta que a especificação de eventos difere, um

    pouco, entre o RCX2 e o Scout. RCX2 usa a macro EVENT_MASK para computar uma

    máscara de evento, enquanto que o Scout as tem pré-definidas.

    Event(EVENT_MASK(3)); // Ativa um evento no RCX2

    Event(EVENT_1_PRESSED)); // Ativa um evento no Scout

    3.9.1. Eventos do RCX2 RCX2, Spy

    Nota: Spybotics events appear to be very similar to RCX2 events, although very

    little testing has been done for the NQC API y Spybotics. A informação seguinte foi

    escrita sobre a perspectiva do RCX2, e não tem sido todavia atualizada para Spybotics.

    O RCX2 e Spybotics oferecem um sistema de eventos, extremamente, flexível.

    Existem 16 eventos, cada um deles se relaciona com uma das diferentes fontes de

    eventos (o estímulo que pode fazer disparar o evento) e o tipo de evento (o critério para

    que se dispare).

    Outros argumentos podem ser especificados dependendo do tipo de evento. Para

    todas as chamadas desde uma função, um evento se identifica por seu número de evento

    uma constante entre 0 e 15. Fontes de eventos são os sensores, temporizadores,

    contadores ou o buffer de mensagens. Um evento é configurado chamando a

    SetEvent(evento, fonte, tipo), onde evento é um número constante (0-15), fonte é a fonte

    do evento, e tipo é um dos tipos que se mostram a continuação (algumas combinações

    de fontes e tipos não são possíveis).

  • ____________________Guia do programador de NQC________________________

    40

    Tipo de Evento Condição Fonte do Evento

    EVENT_TYPE_PRESSED Valor muda para on Somente Sensores

    EVENT_TYPE_RELESASED Valor muda para off Somente Sensores

    EVENT_TYPE_PULSE Valor muda de off a on e outra vez a off Somente Sensores

    EVENT_TYPE_EDGE Valor muda de on para off e vice-versa Somente Sensores

    EVENT_TYPE_FASTCHANGE Valor varia rapidamente Somente Sensores

    EVENT_TYPE_LOW Valor muda para low Todos

    EVENT_TYPE_NORMAL Valor muda para normal Todos

    EVENT_TYPE_HIGHT Valor muda para hight Todos

    EVENT_TYPE_CLICK Valor muda de low para hight e outra vez a low

    Todos

    EVENT_TYPE_DUOBLECLICK

    Dois clicks durante um determinado tempo Todos

    EVENT_TYPE_MESSAGE Nova mensagem recebida Somente mensagem

    Os primeiros quatro eventos baseiam-se no valor booleano de um sensor, assim

    que são mais úteis com sensores de contato. Por exemplo, para configurar o evento #2

    que se dispare quando o sensor de contato da porta 1 é pressionado, pode ser assim:

    SetEvent(2,SENSOR_1,EVENT_TYPE_PRESSED);

    Quando se queria usar EVENT_TYPE_PULSE o EVENT_TYPE_EDGE, o sensor

    tem que estar configurado como SENSOR_MODE_PULSE o SENSOR_MODE_EDGE

    respectivamente.

    EVENT_TYPE_FASTCHANGE deve ser usado com sensores que tenham sido

    configurados com um argumento slope. Quando o valor raw troca mais rápido que o

    argumento slope um evento EVENT_TYPE_FASTCHANGE se disparará.

    Os seguintes três tipos (EVENT_TYPE_LOW, EVENT_TYPE_NORMAL e

    EVENT_TYPE_HIGH) convertem o valor fonte do evento em uma das três escalas (low

    [baixa], normal ou high[alta]), e o evento disparará quando o valor passar de uma

    escala a outra. As escalas são definidas por lower limit (limite inferior) e upper limit

    (limite superior) para o evento. Quando o valor fonte é menor que o limite inferior, a

    fonte será considerada baixa. Quando o valor fonte seja maior que o limite superior, a

    fonte será considerada alta. A fonte será normal, quando estiver entre os dois limites.

    O seguinte evento configura o evento #3 para que dispare quando o valor do

    sensor na porta 2 estiver na escala alta. O limite superior está estabelecido em 80 e o

    limite inferior em 50. Esta configuração é um exemplo de como um evento pode

    disparar quando o sensor de luz detecta luz clara.

    SetEvent(3,SENSOR_2,EVENT_TYPE_HIGH);

    SetLowerLimit(3,50);

  • ____________________Guia do programador de NQC________________________

    41

    SetUpperLimit(3,80);

    O argumento hysteresis pode ser usado para fazer com que as transições sejam

    mais estáveis, nos casos em que o valor varia. O delay funciona fazendo com que a

    transição de baixa a normal seja um pouco mais ampla que a transição de normal a

    baixa.

    Assim, faz com que seja mais fácil entrar na escala baixa que sair dela.