Dentro da área de software, se o número de configurações distintas de brilho necessárias não for muito grande, pode ser útil armazenar os dados no formato "bit-planar" (conforme descrito em minha outra resposta baseada em hardware) e, em seguida, ter o As rotinas de saída usam operadores booleanos para atuar em 8 pixels de uma vez. Para máxima eficiência, isso exigirá ter várias rotinas de saída separadas, usadas para diferentes partes do ciclo do PWM; por exemplo, se desejar usar valores de brilho de 4 bits, use oito rotinas do formulário:
movf bit0Comp, w; Deve ser 00 ou FF, dependendo do bit 0 do comparando (FF, se estiver claro)
iorwf POSTINCF, w; Bit 0 de dados; sempre use IORWF
ewf POSTINCF, w; Bit 1 de dados; use IORWF se o bit 1 do comparando estiver definido; ANDWF se claro
ewf POSTINCF, w; Bit 2 de dados; Use IORWF se o bit 1 do comparando estiver definido; ANDWF se claro
ewf POSTINCF, w; Bit 2 de dados; Use IORWF se o bit 1 do comparando estiver definido; ANDWF se claro
movwf SPIREG; Armazenar byte resultante (bits definidos se> = comparando)
Um poderia usar combinações diferentes de IORWF e ANDWF, dependendo do valor do comparando. Observe que, usando essa abordagem como ilustrado, é possível atualizar os valores de brilho do pixel em qualquer ponto do ciclo do PWM sem tremulação, desde que todos os quatro bits sejam gravados entre as chamadas para a rotina de troca de exibição ou fazendo com que a rotina de atualização de pixel determine se o o próximo turno produzirá um "1" ou um "0" para o pixel, e definir ou limpar todos os bits do pixel (qualquer operação que faça o que for necessário de qualquer maneira) e, em seguida, escrever os bits cujo valor deve seja oposto. Observe também que é possível atingir escalas de brilho não lineares arbitrárias variando o tempo das atualizações do monitor ou usando alguns valores de comparação e mais de uma vez em um ciclo PWM.