Dentro del ámbito del software, si el número de configuraciones de brillo distintas que uno necesita no es demasiado grande, puede ser útil almacenar los datos en formato "plano de bits" (como se describe en mi otra respuesta basada en hardware) y luego tener el Las rutinas de salida utilizan operadores booleanos para actuar en 8 píxeles a la vez. Para una máxima eficiencia, esto requerirá tener múltiples rutinas de salida separadas, usadas para diferentes partes del ciclo PWM; por ejemplo, si uno desea usar valores de brillo de 4 bits, usaría ocho rutinas de la forma:
movf bit0Comp, w; Debe ser 00 o FF dependiendo del bit 0 del comparando (FF si está libre)
iorwf POSTINCF, w; Bit 0 de datos; siempre use IORWF
andwf POSTINCF, w; Bit 1 de datos; use IORWF si el bit 1 de comparand está establecido; ANDWF si está claro
andwf POSTINCF, w; Bit 2 de datos; Use IORWF si el bit 1 de comparand está establecido; ANDWF si está claro
andwf POSTINCF, w; Bit 2 de datos; Use IORWF si el bit 1 de comparand está establecido; ANDWF si está claro
movwf SPIREG; Almacenar el byte resultante (bits establecidos si> = comparand)
Uno usaría diferentes combinaciones de IORWF y ANDWF, dependiendo del valor del comparand. Tenga en cuenta que usando este enfoque como se ilustra, uno puede actualizar los valores de brillo de píxeles en cualquier punto del ciclo PWM sin parpadeo, siempre que los cuatro bits se escriban entre las llamadas a la rutina de cambio de pantalla, o al hacer que la rutina de actualización de píxeles determine si el el próximo turno generará un "1" o un "0" para el píxel, y configurará o borrará todos los bits del píxel (la operación que haga que haga lo que sea que vaya a hacer de todos modos) y luego escriba los bits cuyo valor debería ser opuesto Tenga en cuenta también que se pueden lograr escalas de brillo no lineales arbitrarias variando el tiempo de las actualizaciones de la pantalla o usando algunos valores de comparandos más de una vez en un ciclo PWM.