quinta-feira, fevereiro 09, 2023

Examinando um Display e-paper - Parte 2

A demora entre este post e o anterior se deve a alguns problemas pessoais e algumas dificuldades técnicas. Neste post vou falar um pouco sobre estas últimas e o suporte a displays no CircuitPython.

Algo de errado não está certo...


O objetivo de usar o display com o CircuitPython é poder contar com uma infraestrutura poderosa para a apresentação de imagens, gráficos e textos. A classe usada para isso é a displayio (você pode ler mais sobre ela em https://learn.adafruit.com/circuitpython-display-support-using-displayio, precisa fazer cadastro).

A classe displayio possui algumas subclasses importantes:

  • Display é a classe que inicializa o display e envia a imagem final para ele
  • TileGrid e Group são classes para agrupar o que será apresentado
  • Bitmap, Shape e Pallet são classes para gerar as imagens que serão adicionadas aos TileGrids

O que interessa para nós, no momento, é a classe Display. Existem algumas classes derivadas para certos tipos específicos de display, inclusive a EPaperDisplay. Olhando o construtor desta classe, observamos que tem um número absurdo de parâmetros:



Esta classe não é para ser usada diretamente, deve-se usar uma classe derivada dela que especifique os comandos usados pelo display (o chamado driver). É aqui que a coisa complica.

De um modo geral, os controladores de displays possuem uma interface semelhante. Comandos e dados são enviados ao controlador através de alguma interface serial (I2C, SPI) ou paralela (normalmente 4 ou 8 bits). Nos controladores mais simples (como o tradicional HD44780 usado em display alfanuméricos) os códigos dos comandos incluem os parâmetros necessários e dados vão sempre para uma memória que contém o que vai ser apresentado. Os controladores gráficos são mais complicados e comandos são seguidos de dados com os parâmetros. A escrita (e eventualmente leitura) na memória da tela é feita através de um comando específico. Os códigos dos comandos, os parâmetros de cada um e a codificação destes parâmetros varia conforme o controlador.

Olhando a documentação de EPaperDisplay e os exemplos de drivers da Adafruit, percebemos que displayio se baseia em um conjunto de suposições sobre os comandos e parâmetros. Apesar da grande quantidade de parâmetros no construtor, certas coisas não podem ser mudadas. E o controlador do display que estou usando tem algumas peculiaridades.

O meu primeiro problema foi na construção da sequência de iniciação. Para iniciar o display é preciso enviar uma série de comandos e seus parâmetros, que são codificados de uma forma específica: comando, tamanho dos parâmetros, parâmetros e delay após o comando (opcional). No exemplo que usei como partida não tinha este delay e isto me induziu a um erro. O problema é que um dos comandos de iniciação do display tem um número absurdo de parâmetros (153 bytes) e o bit mais significativo do tamanho indica a presença do delay no final. A solução é indicar que o tamanho será codificado em dois bytes. Resolvido isso eu consegui obter uma imagem, mas sempre um conjunto aleatório de pontos.

Hora de baixar o nível.

Os fontes do CircuitPython e suas bibliotecas estão no github. O código para displayio está em https://github.com/adafruit/circuitpython/tree/main/shared-module/displayio. Reparar que o código está em C (provavelmente para uma melhor performance).

Após muito tempo olhando o código acho que encontrei o problema (podem existir outros): a codificação dos comandos de endereçamento de linha (Y). Existem dois comandos onde são usados o número da linha. Apesar do display ter 200 linhas, o controlador suporta mais e espera que o número da linha venha em dois bytes, com o menos significativo primeiro. Já a coluna (X) é codificada em um único byte.

O código do displayio só prevê dois casos:
  • se a "altura da RAM" for menor que 256, um byte é usado
  • se a "altura da RAM" for maior que 255, usa dois bytes com o mais significativo primeiro
Seguindo os exemplos, eu estava colocando a "altura da RAM" como 200 e o código enviava só um byte de parâmetro quando eram esperados dois. Colocando um valor acima de 255 não resolveu, pois aí vão dois bytes mas na ordem errada.

Por enquanto acho que vou ter que desistir do CircuitPython (pelo menos usando o displayio).

Nenhum comentário: