Jeffrey Cross
Jeffrey Cross

Criando um gerenciador de janelas para um microcontrolador

Este post foi originalmente escrito por Andrew Rossignol e publicado na The Resistor Network em 4 de abril. Ele é republicado aqui em MAKE com permissão.

Eu tenho experimentado com o controlador VGA do uVGA-II nas últimas duas semanas. É uma peça divertida de hardware que é capaz de desenhar gráficos em um framebuffer VGA. O controlador VGA cuida de algoritmos de desenho de linha e ajuda a acelerar o desenho de primitivos geométricos (quadrados, círculos, triângulos, polígonos, linhas).

Depois que percebi o poder desse hardware, decidi implementar um gerenciador de janelas como você esperaria em qualquer PC padrão. Eu usei um mouse para entrada do usuário no sistema.

Close-up da configuração padrão

O sistema padrão inicializa com três aplicativos: Gerenciador de temas, Reprodutor de áudio. e fábrica de janelas. O Theme Manager é usado para modificar as cores do tema do sistema, o Audio Player é usado para reproduzir alguns arquivos de áudio armazenados em um cartão SD e o Window Factory é usado para criar novas janelas para fins de demonstração.

Tema levemente azul, com mais janelas

Aqui está um vídeo demonstrando o sistema.

Visão geral do software

Eu tentei manter camadas de abstração dentro deste software. Vou começar explicando a abordagem em camadas que tomei para os drivers, o gerenciador de janelas e o aplicativo do usuário.

Uma abordagem em camadas

Na parte inferior da pilha está o driver UART. Meu MCU tem dois módulos UART para que eu possa interagir com o uVGA-II e o mouse serial simultaneamente.

Infelizmente caí na armadilha de tentar escrever um bom código e há um borrão entre as camadas. O gerenciador de janelas faz chamadas diretamente para a camada uVGA-II, o que significa que seria difícil portar este gerenciador de janelas para outro controlador VGA. Isso pode ser resolvido criando uma camada intermediária de interface de hardware independente de plataforma. Se um usuário desejasse executar o AVRDE usando outro controlador VGA, ele alteraria a camada de abstração de hardware em vez do próprio gerenciador de janelas.

Apesar do borrão entre as camadas, acho fácil de manter. Consegui adicionar um novo widget (o controle deslizante) em algumas horas.

Modelando um Kit de Ferramentas da GUI em C

Esta é minha primeira tentativa de usar C para modelar abstração complexa. Normalmente, estou usando C para controlar hardware, registradores e outros conceitos de hardware de baixo nível. Este projeto toma uma direção completamente diferente e tenta modelar a metáfora da área de trabalho. Eu não pretendo saber C ++, então eu decidi ficar dentro do meu elemento e usar estruturas e uniões em C.

Todos os objetos na tela são descendentes do widget

O dWidget_t tem uma união anônima de todos os tipos filhos. Isso permite que o objeto dWidget_t seja o tipo pai de todos os widgets da área de trabalho. Os retornos de chamada mouseDown, mouseMove e mouseUp do objeto pai dWidget_t são manipulados pelo próprio gerenciador de janelas. Os ponteiros de função dentro dos tipos “herdados” são para os aplicativos do usuário. Eu ligo para o callback valueChange () para lidar com mudanças de tema.

Gerenciando o Windows

Além do tipo dWidget_t, eu implementei um dManager_t. Essa estrutura é usada para manter as janelas e os retornos de chamada de função associados.

Gerenciador de Janelas

Este gerenciador struct controla o tamanho do gerenciador de janelas (para evitar constantes codificadas), alguns aspectos do cursor, uma lista de ponteiros de janela e as posições e tamanhos dos botões na barra de tarefas.

Desenhando o Desktop

Eu empreguei o algoritmo do Painter para lidar com o desenho das janelas. Isso significa que eu classifico as janelas por Z-Index e, em seguida, as desenho do menor para o maior, de modo que a janela de primeiro plano fique sempre no topo.

Eu pedi emprestado um conceito do Android que eu gosto muito. Eu estou usando uma bandeira de repintura para lidar com repintura quando necessário. Isso significa que, se eu fizer uma modificação em um widget (alterar o texto de um Label, por exemplo), devo chamar dInvalidate () nesse widget para que ele seja pintado na tela. Isso minimiza a quantidade total de repinte necessária.

Eu também tenho uma bandeira de repintura no gerenciador. Esse sinalizador é definido quando uma janela é movida, o tema é alterado ou uma janela é minimizada. O sinalizador manager.repaint resulta em uma repintura completa do ambiente de área de trabalho.

Muitas janelas

Tema do sistema

Cada widget contém um ponteiro para um tema. Isso possibilita que diferentes janelas tenham temas diferentes ou que os aplicativos mantenham sua própria aparência. Eu não explorei essa funcionalidade no vídeo de demonstração.

O gerente também possui uma referência ao tema do sistema para desenhar a barra de tarefas.

A barra de tarefas

A barra de tarefas é bem simples. Ele não é implementado como um widget, ele é simplesmente desenhado em cima do gerenciador de janelas quando necessário e os locais dos botões são armazenados para alternar entre janelas.

Quando os títulos das janelas são muito longos para o botão, os dois últimos caracteres são substituídos por “..”.

Encurtamento de título

Hardware

Não há muito para o hardware. Eu tenho um microcontrolador ATmega1284p, um controlador VGA uVGA-II, um conversor de nível MAX233 e um Microsoft Serial Mouse.

Um close-up do hardware bread-boarded

O código

Eu preciso trabalhar um pouco mais no driver UART e polir alguma documentação antes de fazer o upload do código para o meu repositório Github.

Graças aAndrew Rossignolpor nos permitir repassar seu artigo aqui no site da MAKE.

Ação

Deixar Um Comentário