Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Relatório da Parte 2 do Projeto | Grupo 20
- Escolhas para as representações
- Neste projeto, apesar do seu desenvolvimento ser, de um modo geral, bastante linear, existem alguns detalhes que podem variar consoante a preferência de cada um. São exemplos disso a duração do temporizador e a duração de um ciclo, que definimos como sendo 1/10s e 1/8s, respetivamente, por recomendação do professor. Isto significa que a cada 1/10s (a duração do timer), a posição do objeto vai atualizar o equivalente a 1/8s de movimento. Achamos que eram valores apropriados, uma vez que são valores próximos, e isso significa que o movimento da bola vai ser uma representação próxima da realidade, e o uso de 1/8s para a duração do ciclo (Δ𝑡), que pode ser representado em base 2 (2-3), facilita os cálculos que são feitos ao longo do programa e reduz o erro que estes possuem. Os nossos valores são representados em vírgula fixa, em formato Q10.6, ou seja, dos 16 bits existentes em cada palavra, os 6 menos significativos correspondem à parte fracional do número, e os restantes 10 correspondem à parte inteira. Como usamos complemento para 2 para representar valores negativos, o bit mais significativo representa o sinal do número. Consideramos ainda a aceleração gravítica como 10, representada no formato Q0, que permite uma representação mais simples e, mais uma vez, simplifica os cálculos feitos ao longo do programa.
- Funcionamento do programa
- Assim que o programa inicia, a stack é inicializada, as interrupções são ativadas, e a base do gráfico é escrita no terminal. Entende-se por base do gráfico a primeira e última linha compostas por 80 asteriscos, e a 2ª linha composta por um asterisco em cada extremidade. O gráfico é escrito a partir de 2 funções semelhantes, escrita e escrita2. A primeira escreve a linha superior e inferior, a segunda é responsável pela 2ª linha.
- De seguida, o ciclo principal inicia o temporizador e corre as 5 rotinas principais do nosso código: posicao, limite_pos, aceleracao, velocidade e desenha_bola, pela ordem referida.
- A função posicao, que se manteve inalterada em relação à parte 1 do projeto, recebe pAtual, correspondente à posição anterior e devolve a posição (coloca o novo valor em pAtual) após o movimento, segundo a função 𝑃𝐴𝑡𝑢𝑎𝑙=𝑃𝐴𝑛𝑡𝑒𝑟𝑖𝑜𝑟+𝑉𝐴𝑡𝑢𝑎𝑙×Δ𝑡.
- Após calcular a nova posição, é necessário verificar se atingiu algum dos limites, uma vez que a posição tem de estar sempre entre 1 e 78, inclusive. Sempre que a função atinge um dos limites, ressalta e continua o seu movimento na direção oposta, com velocidade equivalente ao simétrico da sua velocidade antes do ressalto. Para isto, recorremos à função limite_pos. Esta função começa por verificar se a posição atual é superior a 78, e, caso seja, obtém a diferença e retira-a a 78. Isto é, se a posição atual for 78+𝑥, a função devolve 78−𝑥. Caso não tenha atingido o limite superior, a função verifica se passou o limite inferior, 1. Isto é feito de forma semelhante ao limite superior, mas possui uma exceção. O valor é tratado de maneira diferente se for menor que 0 ou se tiver entre 0 e 1.
- Quando o valor é inferior ou igual a 0, obtém-se o seu simétrico e soma-se a 1, ou seja, para uma posição atual 𝑥, com 𝑥<0 , a função devolve o valor 1+(−𝑥). Quando temos uma posição atual 𝑥, com 0<𝑥<1, a função devolve a soma de 1 com a distância percorrida após passar o limite, isto é, (1−𝑥)+1. Após calcular as novas posições, estas são guardadas em pAtual, e como houve um ressalto, obtém-se a velocidade atual e coloca-se o seu simétrico em vAtual. Caso nenhum dos limites seja ultrapassado, a função limite_pos não faz nada.
- Após o cálculo da nova posição, é necessário calcular a velocidade que será responsável pelo movimento seguinte. Para isto, é necessário calcular a aceleração do objeto. Assim, é chamada a função aceleracao, que começa por ler o valor da aceleração da placa (𝑎), aplicando-lhe a fórmula 𝑎÷256×𝑔, com 𝑔, correspondente ao valor da aceleração gravítica, obtido da constante acelg.
- Na verdade, no nosso programa, apenas dividimos o valor da aceleração por 4. Isto deve-se ao facto do valor lido vir no formato Q0, isto é, devido à representação em vírgula fixa que utilizamos (Q6), o valor da aceleração da placa corresponde a 1/64 (2-6) do seu valor real. Assim, para obtermos 𝑎÷256, necessitamos apenas de dividir o valor lido por 4. A multiplicação de 𝑎÷256 por 𝑔 é feita através de uma função auxiliar multiplicar, que é baseada na função de multiplicação que nos foi fornecida na aula de laboratório. Como estamos a trabalhar com vírgula fixa, o produto de quaisquer 2 valores vem no formato Q𝑥, com 𝑥 correspondente à soma do número de bits reservados às casas decimais de cada um dos operandos. Como foi explicado anteriormente, 𝑎÷256 está representado no formato Q6, e como é referido no início deste relatório, a aceleração gravítica, 𝑔, encontra-se no formato Q0. Assim, desta multiplicação obtemos um valor para a aceleração atual em Q6, que é guardada na variável acel.
- Com a aceleração calculada, resta-nos um último cálculo, a velocidade que será utilizada no próximo movimento. À semelhança de posicao, a função velocidade também se manteve inalterada da 1ª parte do projeto. Esta função recebe o valor da velocidade utilizada no ciclo anterior, e, com base na aceleração do objeto, calcula, segundo a fórmula 𝑉𝐴𝑡𝑢𝑎𝑙=𝑉𝑎𝑛𝑡𝑒𝑟𝑖𝑜𝑟+𝑎×Δ𝑡, o valor que o objeto terá para a velocidade no ciclo seguinte.
- Finalmente, após os cálculos estarem concluídos, resta apenas atualizar a posição da bola no terminal. Isto é feito recorrendo à função desenha_bola. Esta função começa por limpar todos as posições possíveis para a bola através da função limpa_linha2, isto é, na 2ª linha coloca um espaço livre em todas as posições de 1 a 78. De seguida, obtém a parte inteira do valor da posição, isto é, passa do formato Q6 para Q0, e coloca a bola na posição correspondente.
- Após todos os cálculos e a atualização da posição da bola no terminal, o programa entra no ciclo check_timer, onde verifica se o registo R4 contém o valor 0. Esta verificação deve-se ao facto de que quando ocorre uma interrupção do temporizador, o registo R4 passa a conter o valor 0. Quando isto ocorre e a função check_timer verifica que o valor em R4 é, de facto, 0, volta ao início da função main, onde o valor de R4 é definido como 1. Este registo, ao longo do programa, é usado exclusivamente para este propósito, por forma a não perturbar o funcionamento do temporizador.
- Escolhemos este método de verificar se o temporizador já tinha terminado, uma vez que a alternativa seria um ciclo que lia a variável TIMER_STATUS. No entanto, por ter de aceder à memória para poder ler esse valor, seria um processo mais demorado, e, por isso, menos eficiente.
- Assim, a partir do momento em que é iniciado, o programa inicia este ciclo, e verificamos uma atualização da posição da bola no terminal a cada 0.1s, como previsto.
- Nota: Enquanto testávamos o projeto, tivemos alguns problemas com o simulador pois o nosso programa não funcionava como devido, tanto no browser como no executável. No entanto, quando experimentamos num dispositivo diferente com um browser diferente, o programa funcionou sem qualquer problema. Mesmo após inúmeras revisões ao código, não conseguimos concluir qual era o erro, por isso assumimos como sendo um erro do simulador.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement