Thumby API
# Introducción
Como hemos comentado ya en algunas de las unidades didácticas anteriores y tras haber estudiado el concepto de Firmware y el Thumby IDE, en lo que sigue vamos a utilizar fundamentalmente las herramientas que proporciona esta última plataforma. Además del IDE, una de los elementos que facilita la programación de Raspberry Pi Pico y en concreto de PiConsole y el hardware de que consta, es la API de Thumby.
API significa Application Programming Interface o Interfaz de Programación de Aplicaciones (opens new window) en español. En general se refiere a una librería que ofrece un conjunto de funciones para facilitar el uso de determinado hardware o servicio. Por ejemplo, la pantalla OLED de PiConsole es un dispositivo hardware conectado a Pico por medio de una conexión SPI (opens new window). La forma de trabajar con ella consiste en enviar a través del interfaz SPI los comandos que el fabricante indica en su datasheet (u hoja de especificaciones). Si echamos un vistazo al datasheet de esta pantalla (opens new window) (página 64), vemos que sólo inicializarla sin llegar a dibujar nada en ella, requiere de 12 comandos. Cualquier operación requerirá un número elevado de estos comandos que además en general resultan muy crípticos para el profano. Como será habitual que sólo requiramos realizar unas pocas operaciones habituales en la pantalla (escribir un texto en una determinada posición, dibujar algunas pocas primitivas gráficas como puntos o rectas, o representar gráficos predibujados), resulta muy práctico preparar una librería que se especialice en estas funciones y nos abstraiga de los comandos de bajo nivel que hay que enviar a la pantalla para realizar esas operaciones.
La API de Thumby que vamos a ver recoge funciones para usar no sólo la pantalla sino también de los 6 controles y el buzzer. Los elementos que tiene PiConsole que no existen en Thumby (el potenciómetro, los LEDs y la fotorresistencia) no están contemplados naturalmente en la librería, por lo que tendremos que acceder a ellos de forma más directa. Vamos a ver a continuación las capacidades de la API de Thumby así como el uso directo de los dispositivos adicionales de PiConsole.
# API Thumby
Los amigos de Thumby tienen su propia documentación de la API en este sitio (opens new window). A continuación vamos a repetir más o menos la información que allí hay, con las pequeñas modificaciones que hemos hecho a la API para que sea compatible con PiConsole. El código de la librería se encuentra en el fichero thumby.py que hay dentro del directorio lib que se crea/instala cuando utilizamos el botón FORMAT del Thumby IDE. La versión que se instala desde el Thumby IDE (opens new window) adaptado para PiConsole, ya incluye las modificaciones necesarias para funcionar correctamente con PiConsole. Puede consultarse en la copia que hay en el repositorio de software de PiConsole en este enlace (opens new window).
# Pantalla
# Constantes
thumby.DISPLAY_W: 128 | Número de píxeles de ancho de la pantallathumby.DISPLAY_H: 64 | Número de píxeles de alto de la pantalla
# Funciones
thumby.display.update()| Actualiza la pantalla con el resultado de haber utilizado las funciones de dibujo que se describen después. Llamar a esta función lo menos posible, sólo cuando hayamos terminado de representar la escena completa, no después de cada orden de dibujo (por ejemplothumby.display.rect(...),thumby.display.drawText(...), etc.).- Devuelve
None
- Devuelve
thumby.display.fill(color)| Cambia todos los píxeles de la pantalla al colorcolor.- Devuelve:
None - Argumentos:
color| tipo: int; valores: 0 o 1 (predeterminado: 0)
- Devuelve:
thumby.display.setPixel(x, y, color)| Cambia el pixel en la posiciónx,yal colorcolor.- Devuelve:
None - Argumentos:
x| tipo: int; valores: 0 (izquierda) ~ 127 (derecha)y| tipo: int; valores: 0 (arriba) ~ 63 (abajo)color| tipo: int; valores: 0 o 1 (predeterminado: 1)
- Devuelve:
thumby.display.drawLine(x1, y1, x2, y2, color)| Dibuja una línea de 1px de espesor con el colorcolordesde la posiciónx1,y1hasta lax2,y2.- Devuelve:
None - Argumentos:
x1| tipo: int; valores: 0 (izquierda) ~ 127 (derecha)y1| tipo: int; valores: 0 (arriba) ~ 63 (abajo)x2| tipo: int; valores: 0 (izquierda) ~ 127 (derecha)y2| tipo: int; valores: 0 (arriba) ~ 63 (abajo)color| tipo: int; valores: 0 o 1 (predeterminado: 1)
- Devuelve:
thumby.display.fillRect(x, y, w, h, color)| Crea un rectángulo relleno del colorcolorcon la esquina superior izquierda en la posiciónx,yy con las dimensionesw(anchura) yh(altura).- Devuelve:
None - Argumentos:
x| tipo: int; valores: 0 (izquierda) ~ 127 (derecha)y| tipo: int; valores: 0 (arriba) ~ 63 (abajo)w| tipo: int; valores: 0 ~ 127h| tipo: int; valores: 0 ~ 63color| tipo: int; valores: 0 o 1 (predeterminado: 1)
- Devuelve:
thumby.display.rect(x, y, w, h, color)| Crea un rectángulo de 1px de espesor del colorcolorcon la esquina superior izquierda en la posiciónx,yy con las dimensionesw(anchura) yh(altura).- Devuelve:
None - Argumentos:
x| tipo: int; valores: 0 (izquierda) ~ 127 (derecha)y| tipo: int; valores: 0 (arriba) ~ 63 (abajo)w| tipo: int; valores: 0 ~ 127h| tipo: int; valores: 0 ~ 63color| tipo: int; valores: 0 o 1 (predeterminado: 1)
- Devuelve:
thumby.display.drawText(string, x, y, color)| Escribe la cadenastringdel colorcoloren la posiciónx,ycon el tipo de letra predeterminado de MicroPython en tamaño 8px x 8px.- Devuelve:
None - Argumentos:
string| tipo: str; valores: 128 caracteres ASCIIx| tipo: int; valores: 0 (izquierda) ~ 127 (derecha)y| tipo: int; valores: 0 (arriba) ~ 63 (abajo)color| tipo: int; valores: 0 o 1 (predeterminado: 1)
- Devuelve:
thumby.display.blit(inspr, x, y, w, h, key)| Dibuja los píxeles definidos en el arrayinspren la posiciónx,yadoptando la anchura y altura indicadas enwyh(lo que se suele llamar un sprite) con cálculos de transparencias indicados enkey(-1: Los píxeles negros se dibujan como negros; 0: Los píxeles negros se tratan como transparentes; 1: Se mezclan los píxeles con cierta operación desconocida).- Devuelve:
None - Argumentos:
x| tipo: int; valores: 0 (izquierda) ~ 127 (derecha)y| tipo: int; valores: 0 (arriba) ~ 63 (abajo)w| tipo: int; valores: 0 ~ 127h| tipo: int; valores: 0 ~ 63key| tipo: int; valores: -1 o 0 o 1 (predeterminado: -1)
- Devuelve:
thumby.display.drawSprite(inspr, x, y, w, h, mirrorX, mirrorY, key)| Dibuja los píxeles definidos en el arrayinspren la posiciónx,yadoptando la anchura y altura indicadas enwyh(lo que se suele llamar un sprite) con la posibilidad de reflejar alrededor de los ejes x e y indicados en los flagsmirrorXymirrorYy con cálculos de transparencias indicados enkey(-1: Los píxeles negros se dibujan como negros; 0: Los píxeles negros se tratan como transparentes; 1: Se mezclan los píxeles con cierta operación desconocida).- Devuelve:
None - Argumentos:
x| tipo: int; valores: 0 (izquierda) ~ 127 (derecha)y| tipo: int; valores: 0 (arriba) ~ 63 (abajo)w| tipo: int; valores: 0 ~ 127h| tipo: int; valores: 0 ~ 63mirrorX| tipo: bool; valores: 1/True (reflejar) o 0/False (no reflejar)mirrorY| tipo: bool; valores: 1/True (reflejar) o 0/False (no reflejar)key| tipo: int; valores: -1 o 0 o 1 (predeterminado: -1)
- Devuelve:
# Teclas
# Objetos
thumby.buttonA| Para acceder a la teclaAthumby.buttonB| Para acceder a la teclaBthumby.buttonU| Para acceder a la direcciónArribaen la crucetathumby.buttonD| Para acceder a la direcciónAbajoen la crucetathumby.buttonL| Para acceder a la direcciónIzquierdaen la crucetathumby.buttonR| Para acceder a la direcciónDerechaen la cruceta
# Funciones
thumby.buttonX.pressed()| DevuelveTruesi la teclathumby.buttonXestá pulsado,Falseen otro caso (sustituirbuttonXpor cualquiera de los objetos de la lista anterior)thumby.buttonX.justPressed()| DevuelveTruesi la última tecla pulsada fuethumby.buttonX,Falseen otro caso (sustituirbuttonXpor cualquiera de los objetos de la lista anterior)
# Sonido
Nota: El sonido no está implementado en el emulador del Thumby IDE, pero es poco probable que produzca excepciones.
# Funciones
thumby.audio.play(freq, duration, duty)| Reproduce una nota de frecuenciafreq, ancho de pulsodutypor una duración dedurationen milisegundos sin bloquear la ejecución del resto del código. Por ahora, intenta buscar "tabla notas musicales frecuencia" para relacionar estos parámetros con notas musicales.- Devuelve:
None - Argumentos:
freq| tipo: int; valores: 7 ~ 125000000 (Hz)duration| tipo: int; valores: 0 ~ 2147483647 (ms)duty| tipo: uint_16; valores: 0 (0%) ~ 65535 (100%) (predeterminado: 32768 equivalente a 50%)
- Devuelve:
thumby.audio.playBlocking(freq, duration, duty)| Reproduce una nota de frecuenciafreq, ancho de pulsodutypor una duración dedurationen milisegundos bloqueando la ejecución del resto del código. Por ahora, intenta buscar "tabla notas musicales frecuencia" para relacionar estos parámetros con notas musicales.- Devuelve:
None - Argumentos:
freq| tipo: int; valores: 7 ~ 125000000 (Hz)duration| tipo: int; valores: 0 ~ 2147483647 (ms)duty| tipo: uint_16; valores: 0 (0%) ~ 65535 (100%) (predeterminado: 32768 equivalente a 50%)
- Devuelve:
thumby.audio.stop()| Detiene la reproducción de cualquier sonido producido porthumby.audio.play(...).- Devuelve:
None
- Devuelve:
thumby.audio.set_enabled(setting)| Desactiva o activa el buzzer de manera que en estado desactivado las funcionesthumby.audio.play()othumby.audio.playBlocking()no producen sonido.thumby.audio.playBlocking(...)seguirá bloqueando la ejecución del código durante la duración indicada en los parámetros.- Devuelve:
None - Argumentos:
setting| tipo: bool; valores: 1/True (activado) o 0/False (desactivado)
- Devuelve:
# Archivos
Precaución: La creación y escritura en ficheros no funciona en el emulador del Thumby IDE y puede causar excepciones.
# Funciones
thumby.files.openFile(filename, options)| Abre el fichero de la ruta completa indicada enfilename(por ejemplo/Games/MyGame/config.txt) con la opción de apertura de ficheros de Python (opens new window) indicada enoptions.- Devuelve:
None - Argumentos:
filename| tipo: str; valores: Ruta ASCII con directorios separados por/options| tipo: str; valores: 'w', 'r', 'wb', 'rb'
- Devuelve:
thumby.files.closeFile()| Cierra el último fichero abierto conthumby.files.openFile(...).- Devuelve:
None
- Devuelve:
thumby.files.setFile(f)| Asocia el fichero manejado internamente al objeto Python de tipo ficherof(obtenido por ejemplo conf = open(..., ...)).- Devuelve:
None
- Devuelve:
thumby.files.readFile(l)| Leelbytes del fichero abierto conthumby.files.openFile(...).- Devuelve: los
lbytes leídos del fichero o "" si no se ha abierto fichero todavía - Argumentos:
l| tipo: int; valores: 0 ~ 2147483647 (default: -1, read whole file)
- Devuelve: los
thumby.files.writeFile(data)| Escribedataal fichero abierto conthumby.files.openFile(...).- Devuelve:
Truesi ha tenido éxito,Falsesi no, y-1si no se ha abierto fichero todavía - Argumentos:
data| tipo: str, bytes(...), bytearray(...), etc.; valores: texto o binario dependiendo de la opción con que fue abierto el fichero
- Devuelve:
thumby.files.changeDirectory(path)| Cambia el directorio a la rutapath(por ejemplo sipathvale""/Games/MyGame"a partir de entonces podremos hacerf = open("config.txt")).- Devuelve:
None - Argumentos:
path| tipo: str; valores: Ruta ASCII con directorios separados por/
- Devuelve:
thumby.files.getDirectory()| Devuelve un str con la ruta del directorio actual seleccionado.thumby.files.makeDirectory(path)| Crea el directorio indicado enpath.- Devuelve:
None - Argumentos:
path| tipo: str; valores: Ruta ASCII con directorios separados por/
- Devuelve:
Ejemplo rápido
Vamos a mostrar cómo utilizar la API escribiendo un sencillo programa que emplee alguna de las funciones anteriores. Abre el Thumby IDE (opens new window) y teclea en el Editor de código lo siguiente:
import thumby
thumby.display.fill(0) # Rellena pantalla de negro
thumby.display.update() # Refresca pantalla
def nota(tecla, freq):
thumby.display.drawText(tecla, 60, 30, 1) # Dibuja tecla pulsada
thumby.display.update() # Refresca pantalla
thumby.audio.playBlocking(freq, 1000, 32768) # Interpreta nota
thumby.display.fill(0) # Rellena pantalla de negro
thumby.display.update() # Refresca pantalla
while True:
if thumby.buttonA.justPressed(): # Detecta pulsación 'A'
nota("A", 440) # Interpreta nota 'A' (La)
if thumby.buttonB.justPressed(): # Detecta pulsación 'B'
nota("B", 494) # Interpreta nota 'B' (Si)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Pulsa FAST EXECUTE para ejecutarlo en PiConsole. Probarlo pulsando las teclas A y B