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
,y
al 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 colorcolor
desde la posiciónx1
,y1
hasta 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 colorcolor
con la esquina superior izquierda en la posiciónx
,y
y 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 colorcolor
con la esquina superior izquierda en la posiciónx
,y
y 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 cadenastring
del colorcolor
en la posiciónx
,y
con 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 arrayinspr
en la posiciónx
,y
adoptando la anchura y altura indicadas enw
yh
(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 arrayinspr
en la posiciónx
,y
adoptando la anchura y altura indicadas enw
yh
(lo que se suele llamar un sprite) con la posibilidad de reflejar alrededor de los ejes x e y indicados en los flagsmirrorX
ymirrorY
y 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 teclaA
thumby.buttonB
| Para acceder a la teclaB
thumby.buttonU
| Para acceder a la direcciónArriba
en la crucetathumby.buttonD
| Para acceder a la direcciónAbajo
en la crucetathumby.buttonL
| Para acceder a la direcciónIzquierda
en la crucetathumby.buttonR
| Para acceder a la direcciónDerecha
en la cruceta
# Funciones
thumby.buttonX.pressed()
| DevuelveTrue
si la teclathumby.buttonX
está pulsado,False
en otro caso (sustituirbuttonX
por cualquiera de los objetos de la lista anterior)thumby.buttonX.justPressed()
| DevuelveTrue
si la última tecla pulsada fuethumby.buttonX
,False
en otro caso (sustituirbuttonX
por 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 pulsoduty
por una duración deduration
en 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 pulsoduty
por una duración deduration
en 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)
| Leel
bytes del fichero abierto conthumby.files.openFile(...)
.- Devuelve: los
l
bytes 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)
| Escribedata
al fichero abierto conthumby.files.openFile(...)
.- Devuelve:
True
si ha tenido éxito,False
si no, y-1
si 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 sipath
vale""/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