aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsejo <sejo@texto-plano.xyz>2021-05-20 17:57:40 -0500
committersejo <sejo@texto-plano.xyz>2021-05-20 17:57:40 -0500
commit5ee0826789dfc0beb432b29104a16b0480884b99 (patch)
tree68df4748f01b0a934a03307fda8d900b1e514600
parent6c3fcba6a012e05a0cbdfafd0dc5651a1ec2aba4 (diff)
downloadsitio-5ee0826789dfc0beb432b29104a16b0480884b99.tar.gz
fecha holoceno
-rw-r--r--gem/avr-asm.gmi323
-rw-r--r--gem/coloring_computers.gmi51
-rw-r--r--gem/compudanzas.gmi116
-rw-r--r--gem/danzasistemas-tag.gmi80
-rw-r--r--gem/darena.gmi652
-rw-r--r--gem/ffmpeg.gmi114
-rw-r--r--gem/imagemagick.gmi118
-rw-r--r--gem/index.gmi14
-rw-r--r--gem/indice.gmi14
-rw-r--r--gem/logiteca.gmi290
-rw-r--r--gem/recetas.gmi194
-rw-r--r--gem/s-camino.gmi33
-rw-r--r--gem2gem.awk2
-rw-r--r--gemtext2html.awk1
14 files changed, 2001 insertions, 1 deletions
diff --git a/gem/avr-asm.gmi b/gem/avr-asm.gmi
new file mode 100644
index 0000000..61f8d7c
--- /dev/null
+++ b/gem/avr-asm.gmi
@@ -0,0 +1,323 @@
+# avr-asm
+
+explorando programación de microcontroladores avr a través de asm, en attiny85. {s-camino}
+
+=> ./s-camino.gmi {s-camino}
+
+# attiny85
+
+## diagrama de pines
+
+```diagrama de pines
+ ┌──────┐
+PB5 │1 8│ VCC
+PB3 │2 7│ PB2
+PB4 │3 6│ PB1
+GND │4 5│ PB0
+ └──────┘
+```
+
+además, cada pin es:
+
+* 1: PB5 / PCINT5 / ~RESET / ADC0 / dW
+* 2: PB3 / PCINT3 / XTAL1 / CLKI / ~OC1B / ADC3
+* 3: PB4 / PCINT4 / XTAL2 / CLKO / OC1B / ADC2
+* 5: PB0 / MOSI / DI / SDA / AIN0 / OC0A / ~OC1A / AREF / PCINT0
+* 6: PB1 / MISO / DO / AIN1 / OC0B / OC1A / PCINT1
+* 7: PB2 / SCK / USCK / SCL / ADC1 / T0 / INT0 / PCINT2
+
+para flashear nos interesan los pines desde el punto de vista de SPI:
+
+```pines spi
+ ┌──────┐
+~RESET │1 8│ VCC
+ │2 7│ SCK
+ │3 6│ MISO
+GND │4 5│ MOSI
+ └──────┘
+```
+
+## programador
+
+=> https://www.fischl.de/usbasp/ USBasp - USB programmer for Atmel AVR controllers (web)
+
+## makefile
+
+para ensamblar y flashear
+
+```makefile
+# Makefile
+# nombre del programa sin .S :
+PROG = test
+# config hardware
+BOARD = attiny85
+PROGRAMMER = usbasp
+
+# ensambla programa a .hex
+hex:
+ avr-gcc -Os -DF_CPU=8000000 -mmcu=$(BOARD) -c $(PROG).S
+ avr-ld -o $(PROG).elf $(PROG).o
+ avr-objcopy $(PROG).elf -O ihex $(PROG).hex
+ rm $(PROG).o $(PROG).elf
+
+# flashea
+flash:
+ avrdude -c $(PROGRAMMER) -p $(BOARD) -U flash:w:$(PROG).hex:i
+
+# lee la memoria flash a read.hex
+read:
+ avrdude -c $(PROGRAMMER) -p $(BOARD) -U flash:r:read.hex:i
+
+# prueba conexión con programador y micro
+test:
+ avrdude -c $(PROGRAMMER) -p $(BOARD)
+```
+
+
+
+# programas
+
+software experimental, compartido como referencia y sin garantía de ningún tipo :)
+
+
+## test.S
+
+enciende un el pin PB0 — conecta un led
+
+```
+; test.S
+; enciende un pin
+#include <avr/io.h>
+.org 0x0000
+
+ ldi r17, (1<<DDB0) ; configura al PB0 como salida
+ sts DDRB, r17
+
+ ldi r16, (1<<PB0) ; enciende el bit correspondiente al PB0
+ sts PORTB, r16 ; actualiza el puerto
+
+ sleep ; duerme por siempre (?)
+```
+
+## blink.S
+
+parpadea el pin PB0 usando el timer/counter0 — conecta un led
+
+```
+; blink.S
+; parpadea el pin PB0 (OC0A)!
+; r16 y r17 se usan como registros auxiliares
+
+; el programa usa el timer/counter 0 con:
+; * waveform generation mode (WGM0): 2, que es CTC (clear timer on compare match)
+; * compare match output A mode (COM0A): 1, que es toggle en compare match
+; * clock select (CS0): 5, que utiliza el reloj i/o dividido entre 1024
+
+; notas sobre el reloj:
+; por default el attiny85 va a 8MHz, y el reloj i/o va a 1MHz
+; 1MHz/1024 ~= 967 Hz
+
+#include <avr/io.h>
+; ***********************
+; vectores de interrupts:
+; ***********************
+; Reset
+.org 0x0000
+ rjmp main
+
+; ***********************
+; Main
+; ***********************
+.org 0x0010
+main:
+ ; pin PB0 (OC0A) como pin de salida
+ ldi r16, (1<<DDB0) ; pin de salida
+ sts DDRB, r16
+
+ ; togglea OC0A en Compare match (1 en COM0A[1:0])
+ ; y usa modo Clear Timer on Compare Match (2 en WGM0[2:0])
+ ldi r16, (0<<COM0A1) | (1<<COM0A0) | (1<<WGM01) | (0<<WGM00)
+ sts TCCR0A, r16
+
+ ; completa el modo WGM (waveform generaton mode, bit 2)
+ ; establece el tipo de reloj: 0b101 en CS0 es clk/1024
+ ldi r16, (0<<WGM02) | (1<<CS02) | (0<<CS01) | (1<<CS00)
+ sts TCCR0B, r16
+
+ ; el TOP es el valor en OCR0A
+ ldi r16, 0x80
+ sts OCR0A, r16
+
+loop:
+ sleep
+ rjmp loop
+```
+
+## buzz.S
+
+zumba el pin PB0 — conecta un buzzer
+
+```
+; buzz.S
+; haz zumbar el pin PB0 (OC0A)!
+; el código es igual a blink.S, pero con diferentes frecuencias
+; r16 y r17 se usan como registros auxiliares
+
+; el programa usa el timer/counter 0 con:
+; * waveform generation mode (WGM0): 2, que es CTC (clear timer on compare match)
+; * compare match output A mode (COM0A): 1, que es toggle en compare match
+; * clock select (CS0): 4, que utiliza el reloj i/o dividido entre 256
+
+; notas sobre el reloj:
+; por default el attiny85 va a 8MHz, y el reloj i/o va a 1MHz
+; 1MHz/256 ~= 3906 Hz (/2 para el periodo completo ~=1953Hz)
+
+#include <avr/io.h>
+; ***********************
+; vectores de interrupts:
+; ***********************
+; Reset
+.org 0x0000
+ rjmp main
+
+; ***********************
+; Main
+; ***********************
+.org 0x0010
+main:
+ ; pin PB0 (OC0A) como pin de salida
+ ldi r16, (1<<DDB0) ; pin de salida
+ sts DDRB, r16
+
+ ; togglea OC0A en Compare match (1 en COM0A[1:0])
+ ; y usa modo Clear Timer on Compare Match (2 en WGM0[2:0])
+ ldi r16, (0<<COM0A1) | (1<<COM0A0) | (1<<WGM01) | (0<<WGM00)
+ sts TCCR0A, r16
+
+ ; completa el modo WGM (waveform generaton mode, bit 2)
+ ; establece el tipo de reloj: 0b100 en CS0 es clk/256
+ ldi r16, (0<<WGM02) | (1<<CS02) | (0<<CS01) | (0<<CS00)
+ sts TCCR0B, r16
+
+ ; el TOP es el valor en OCR0A
+ ldi r16, 0x02
+ sts OCR0A, r16
+
+loop:
+ sleep
+ rjmp loop
+```
+
+## alarm.S
+
+zumbido intermitente en el pin PB0 — conecta un buzzer
+
+```
+; alarm.S
+; zumbido intermitente en el pin PB0 (OC0A)!
+; r16 y r17 se usan como registros auxiliares
+; r20 tiene el valor de TCCR0A para apagar sonido
+; r21 tiene el valor de TCCR0A para encenderlo
+
+; el programa usa el timer/counter 0 con:
+; * waveform generation mode (WGM0): 2, que es CTC (clear timer on compare match)
+; * compare match output A mode (COM0A): 1, que es toggle en compare match
+; * clock select (CS0): 3, que utiliza el reloj i/o dividido entre 64
+
+; y el timer/counter 1 con:
+; * clock select (CS1): 0b1010, que es clk/512
+; * interrupciones de overflow y de compare match A:
+; - en compare match A el zumbido se apaga
+; - en overflow el zumbido inicia
+
+; notas sobre el reloj:
+; por default el attiny85 va a 8MHz, y el reloj i/o va a 1MHz
+; 1MHz/256 ~= 3906 Hz (/2 para el periodo completo ~=1953Hz)
+
+#include <avr/io.h>
+; ***********************
+; vectores de interrupts:
+; ***********************
+; Reset
+.org 0x0000
+ rjmp main
+
+; dirección 0x0003 * 2
+.org 0x0006
+ rjmp timer1compareA_isr
+
+; dirección 0x0004 * 2
+.org 0x0008
+ rjmp timer1overflow_isr
+
+; ***********************
+; Main
+; ***********************
+.org 0x001E
+main:
+ ;----------------------------------
+ ; configuración general
+ ;----------------------------------
+
+ ; habilita interrupciones
+ sei
+
+ ; pin PB0 (OC0A) como pin de salida
+ ldi r16, (1<<DDB0) ; pin de salida
+ sts DDRB, r16
+
+ ; valores de TCCR0A para encender o apagar sonido
+ ldi r20, (0<<COM0A1) | (0<<COM0A0) | (1<<WGM01) | (0<<WGM00)
+ ldi r21, (0<<COM0A1) | (1<<COM0A0) | (1<<WGM01) | (0<<WGM00)
+
+ ;----------------------------------
+ ; configuración TIMER0 para buzzer
+ ;----------------------------------
+ ; togglea OC0A en Compare match (1 en COM0A[1:0])
+ ; y usa modo Clear Timer on Compare Match (2 en WGM0[2:0])
+ sts TCCR0A, r21
+
+ ; completa el modo WGM (waveform generaton mode, bit 2)
+ ; establece el tipo de reloj: 0b011 en CS0 es clk/64
+ ldi r16, (0<<WGM02) | (0<<CS02) | (1<<CS01) | (1<<CS00)
+ sts TCCR0B, r16
+
+ ; el TOP es el valor en OCR0A
+ ; más pequeño es más agudo
+ ldi r16, 0x06
+ sts OCR0A, r16
+
+ ;----------------------------------
+ ; configuración TIMER1 para alternar entre sonido on/off
+ ;----------------------------------
+ ; CS1 en 0b1010 es CK/512
+ ldi r16, (1<<CS13) | (0<<CS12) | (1<<CS11) | (0<<CS10)
+ sts TCCR1, r16
+
+ ; establece el valor A al que cuenta el timer1 antes de apagar sonido
+ ; menor valor, menor tiempo de sonido (duty cycle)
+ ldi r16, 0x30
+ sts OCR1A, r16
+
+ ; set Timer overflow interrupt enable 1
+ ; y timer output compare A interrupt enable 1
+ ldi r16, (1<<TOIE1) | (1<<OCIE1A)
+ sts TIMSK, r16
+
+loop:
+ sleep
+ rjmp loop
+
+timer1compareA_isr:
+ ; apaga la salida
+ sts TCCR0A, r20
+ reti
+
+timer1overflow_isr:
+ ; enciende la salida
+ sts TCCR0A, r21
+ ; regresa de la interrupción
+ reti
+```
+
+página actualizada en: sejmana-1660, día 1 (12021-05-20)
diff --git a/gem/coloring_computers.gmi b/gem/coloring_computers.gmi
new file mode 100644
index 0000000..335eb0d
--- /dev/null
+++ b/gem/coloring_computers.gmi
@@ -0,0 +1,51 @@
+# coloring computers
+
+non-electronic computers that work when you color them according to a simple set of rules.
+
+an exploration of computation without electricity and semiconductors, an attempt to reinvent digital systems away from efficiency and productivity, and hopeful prototypes to expose the inner workings of computers.
+
+# 4-bits to 7-segment display hexadecimal decoder (12020)
+
+=> ./img/foto_20201130_hex7segdecoder_01.png the coloring computer/decoder, waiting to be activated
+=> ./img/foto_20201130_hex7segdecoder_02.png a human coloring the wires according to the logic rules
+=> ./img/foto_20201130_hex7segdecoder_03.png the coloring computer/decoder, with an input of 0011, and an output that can be read as 3
+
+a coloring decoder built with NOT (triangle), AND (semicircle), and OR (the other shape (?)) gates, based on a manual design.
+
+=> ./img/dibujo_20201207_hex7segdecoder_small.png the complete decoder
+
+=> https://opguides.info/engineering/digitallogic/ colored and animated version by Vega
+=> https://ipfs.io/ipfs/QmZv53hr7QEzxrPaRNpiyU9VUNHw9UgyaTUqYD9x9iFpNA/dibujo_20201207_hex7segdecoder.png download the decoder in full size 1487x3057 (png, ~446KB)
+
+# computadora no(r)pal (12019)
+
+=> ./img/dibujo_20190715-norpalera-fulladder_blanco_small.png logic circuit in the shape of nopal
+
+a full-adder built with nor gates (see {logiteca}) in the shape of no(r)pales
+
+=> ./logiteca.gmi {logiteca}
+
+=> https://ipfs.io/ipfs/QmPz2D3bZRYFi1HnfiNJB8o9TZZvH8atuYpFixMKccYCYP/dibujo_20190715-norpalera-fulladder_blanco.png download computadora no(r)pal in full size 1200x1600 (png, ~429KB)
+
+# coloring computers (12018)
+
+the original ones
+
+=> ./img/foto_coloring-computers_cover-lee.png photo of the cover of the zine, colored
+=> ./img/foto_coloring-computers_7seg-lee.png photo of a pair of colored pages of the zine, with a 7 segment display showing the digits 2 and 3
+=> ./img/foto_coloring-computers_pcd2019.png photo of a pair of colored pages of the zine, showing a digital circuit answering if two colors are the same
+
+the booklet contains three series of computers: computers that compare, computers that count, and computers that play. they are all NOR-based logic circuits designed by using truth tables, karnaugh maps, and maxterm expansions.
+
+=> https://ipfs.io/ipfs/QmYz7DPRWypGQcbAHr7Mi8EKB6ntSPsEnUsCXbAhBiHQZP/ original site and resources
+=> https://ipfs.io/ipfs/QmYz7DPRWypGQcbAHr7Mi8EKB6ntSPsEnUsCXbAhBiHQZP/coloringcomputers_pages.pdf download the page-by-page zine (pdf, ~1.5MB)
+=> https://ipfs.io/ipfs/QmYz7DPRWypGQcbAHr7Mi8EKB6ntSPsEnUsCXbAhBiHQZP/coloringcomputers.pdf download the ready-to-print-and-cut zine (pdf, ~1.4MB)
+
+CC-BY-SA 4.0
+
+for the print and cut zine: print double-sided, cut in half, fold the pages and assemble
+
+presented as a workshop in the
+=> https://processing.nyc/2019/#workshops processing community day nyc 2019
+
+página actualizada en: sejmana-1660, día 1 (12021-05-20)
diff --git a/gem/compudanzas.gmi b/gem/compudanzas.gmi
new file mode 100644
index 0000000..59331c6
--- /dev/null
+++ b/gem/compudanzas.gmi
@@ -0,0 +1,116 @@
+# compudanzas
+
+materializando ciencias computacionales en cuerpxs humanxs y coreografía
+
+# el taller
+
+## abstract
+
+el taller de compudanzas materializa ciencias computacionales en cuerpxs humanxs y coreografía.
+
+¿qué es una computadora? ¿cómo es tan poderosa y hace lo que hace, si “solo” consiste en minerales super ordenados a través de procesos complejos?
+
+¿qué pasa si la alentamos? ¿y si incrementamos su tamaño? ¿y si le quitamos todo rastro de eficiencia para que la podamos bailar?
+
+en este taller nos insertaremos entre el mundo abstracto de las ciencias computacionales y el mundo de su materialización industrial, para darle cuerpo humano, social, coreográfico, a algunos de sus conceptos fundamentales: máquinas de turing, compuertas lógicas, autómatas celulares, arquitectura von neumann, y más.
+
+lo que queremos es construir y programar computadoras relativamente lentas, grandes e ineficientes, a partir de personas en movimiento siguiendo/jugando instrucciones. así, nos podremos reapropiar de las maneras computacionales de entender el mundo, para usarlas a nuestro gusto con el fin de proponer otras posibles computadoras, danzas, y/o vidas.
+
+## justificación
+
+ la miniaturización y aceleración de los circuitos de semiconductores, además de tener un gran costo ambiental, social y económico, dificulta el conocer y entender qué pasa en su interior, y cómo es que logran hacer emerger todas las capacidades que entendemos inherentes al cómputo.
+
+por otro lado, la configuración social actual genera e incrementa una brecha de conocimientos y posibilidades entre unos cuantos que tienen el poder de desarrollar las tecnologías digitales, y el resto de la población al que se le asigna únicamente un rol de consumidor y de fuente de datos a extraer.
+
+por si fuera poco, lo abstracto y ofuscado de las ciencias computacionales y de la forma en que suelen ser compartidas, se oponen a sanar esta brecha de acceso.
+
+es por esto que el taller busca experimentar con otros acercamientos y estrategias para abordar estos temas, tratando no de hablarlos y racionalizarlos sino de bailarlos, sentirlos y recontextualizarlos.
+
+partimos de que todo el cuerpo de conocimientos sobre la computación fue desarrollado por personas con pasiones así como cualquier otra, por lo que las nociones de lo "frío" y "cuadrado" de lo "maquínico" y digital pueden ser entendidas desde una perspectiva que las acerca a lo orgánico, lo fluido, y a nosotras como personas vivas.
+
+dadas las crisis climáticas, ecológicas y sociales actuales, consideramos que el taller es un importante ejercicio de imaginación donde nos preguntamos: ¿qué pasaría si las computadoras fueran bailes y no cajas de metal y semiconductor?
+
+
+## objetivos
+
+* introducir y difundir conceptos fundamentales de la computación a través de estrategias pedagógicas inspiradas en la danza.
+* visibilizar procesos e ideas que rigen las realidades digitales actuales pero que suelen ser accesibles solo para un grupo reducido de personas.
+* instigar la reapropriación de dichos conceptos con el objetivo de imaginar y realizar mundos donde sirven a intereses alternos, como los de la danza, la vida y la liberación.
+* promover el pensar y sentir con el cuerpo, con énfasis en lo computacional por ser algo considerado abstracto y cerebral a pesar de sus múltiples impactos materiales.
+
+
+## temario
+
+los siguientes temas son puntos de partida para los bailes y actividades corporales propuestos, así como para los proyectos creativos de les participantes.
+
+se abordarán los principios teóricos, pero sin ahondar en discusiones abstractas que se alejen mucho del cuerpo
+
+* ciencias computacionales, coreografía, ¿cyborgs?
+* el universo discreto: estados finitos y tiempos discontinuos
+* operaciones lógicas / digitales
+* memoria básica con registro de corrimiento
+* mundo binario: operaciones y compuertas lógicas
+* autómatas celulares y complejidad emergente
+* computación formal
+* sistemas de "tag"
+* máquinas de turing
+* máquina universal de turing
+* organización computacional
+* arquitectura de von neumann
+* código máquina y programación
+
+## agenda
+
+el taller consiste en 6 sesiones de 2 horas de duración cada una
+
+* danzas compuertas
+* autómatas celulares
+* computación formal
+* máquina universal de turing
+* organización computacional
+* integración
+
+# las danzas
+
+sección en construcción
+
+## ciclo de memoria
+
+en la que nos volvemos un registro de corrimiento (shift register) síncrono para almacenar de manera activa una secuencia de símbolos.
+
+## danzas compuertas
+
+en la que nos convertimos en red de compuertas lógicas para resolver en conjunto operaciones aritméticas o lógicas.
+
+comportamiento asíncrono, que podemos sincronizar para procesos más complejos.
+
+=> ./logiteca.gmi {logiteca}
+
+## reglas de wolfram
+
+danzas en las que nuestro nuevo estado individual depende de nuestro estado propio y del de dos personas más.
+
+## danzasistemas-tag
+
+“batallas” en las que respondemos procesando elementos de la secuencia anterior.
+
+=> ./danzasistemas-tag.gmi {danzasistemas-tag}
+
+## d. turing
+
+en donde bailamos con y a partir de una fila / tira / cinta de objetos / símbolos y una tabla específica de estados.
+
+## máquina universal bailable
+
+en donde bailamos con y a partir de una fila / tira / cinta de objetos y una tabla específica de estados, en un acomodo tal que nos permite simularnos bailando con y a partir de una fila / tira / cinta de objetos y cualquier tabla específica de estados
+
+## pequeña persona computadora
+
+en donde nuestras acciones toman la forma de las operaciones de una computadora organizada casi como las que conocemos.
+
+enlazan aquí:
+=> ./danzasistemas-tag.gmi {danzasistemas-tag}
+=> ./logiteca.gmi {logiteca}
+
+
+página actualizada en: sejmana-1660, día 1 (12021-05-20)
diff --git a/gem/danzasistemas-tag.gmi b/gem/danzasistemas-tag.gmi
new file mode 100644
index 0000000..4f57ca5
--- /dev/null
+++ b/gem/danzasistemas-tag.gmi
@@ -0,0 +1,80 @@
+# danzasistemas-tag
+
+una compudanza basada en máquina abstracta (tag systems, o bien, máquina de post)
+
+=> ./compudanzas.gmi {compudanzas}
+
+# descripción
+
+las danzasistemas-tag consisten en "batallas" de baile en las que alternamos recibiendo y respondiendo secuencias de movimiento.
+
+las secuencias que respondemos son producto de procesar elementos de la secuencia que recibimos.
+
+# indicaciones
+
+necesitamos los siguientes elementos:
+
+* A: alfabeto finito de símbolos/movimientos identificables y replicables
+* P: las reglas de producción: qué símbolos/movimientos hay que agregar al final de la nueva secuencia, de acuerdo al primer símbolo/movimiento de la secuencia recibida.
+* m: número de eliminación: cuántos símbolos/movimientos hay que eliminar del inicio de la secuencia recibida.
+
+al recibir una secuencia de movimiento, hemos de poner atención y realizar lo siguiente para construir nuestra respuesta:
+
+* notar el primer símbolo/movimiento, que nos indica qué regla de producción seguir al final de la secuencia.
+* descartar la cantidad de símbolos/movimientos del inicio de la secuencia de acuerdo al número de eliminación. (esto incluye al primer símbolo/movimiento).
+* memorizar y replicar la secuencia recibida a partir de ese punto, en orden y hasta el final.
+* agregar el o los símbolos/movimientos al final de la secuencia, de acuerdo a la regla de producción.
+
+según la danzasistema-tag, la dinámica de respuestas continúa hasta llegar al símbolo/movimiento que indique detenerse, o hasta que la secuencia de movimiento quede vacía.
+
+# ejemplo
+
+cómputo de secuencias de collatz, tomado de wikipedia
+
+=> https://en.wikipedia.org/wiki/Tag_system#Example:_Computation_of_Collatz_sequences Tag system - Example: Computation of Collatz sequences (web)
+
+los elementos de nuestra danzasistema-tag serían los siguientes:
+
+## A: alfabeto finito de símbolos/movimientos
+
+tres símbolos/movimientos: a, b, c
+
+## P: reglas de producción
+
+si primer símbolo/movimiento es 'a', agrega 'bc' al final.
+
+si primer símbolo/movimiento es 'b', agrega 'a' al final.
+
+si primer símbolo/movimiento es 'c', agrega 'aaa' al final.
+
+nota cómo cada regla de producción agrega una cantidad distinta de símbolos/movimientos al final.
+
+## m: número de eliminación
+
+en este caso, siempre descartaremos 2 símbolos/movimientos del inicio de la secuencia.
+
+## desarrollo
+
+partiendo de una secuencia inicial 'aaa'...
+
+```
+inicio: aaa
+respuesta: abc
+respuesta: cbc
+respuesta: caaa
+respuesta: aaaaa
+respuesta: aaabc
+respuesta: abcbc
+respuesta: cbcbc
+etc...
+```
+
+siempre se descartan los 2 símbolos/movimientos del inicio, pero la cantidad de símbolos/movimientos que se agregan al final cambian de acuerdo a la regla de producción.
+
+esta dinámica de respuestas a partir de esa secuencia inicial, eventualmente termina descartando a la secuencia completa.
+
+enlaza aquí {compudanzas}
+
+=> ./compudanzas.gmi {compudanzas}
+
+página actualizada en: sejmana-1660, día 1 (12021-05-20)
diff --git a/gem/darena.gmi b/gem/darena.gmi
new file mode 100644
index 0000000..3bf8162
--- /dev/null
+++ b/gem/darena.gmi
@@ -0,0 +1,652 @@
+# darena
+
+an open-ended game of rocks and sand
+
+the sandy space contains a bunch of rocks in either one of two possible colors, and yourself.
+
+push and arrange the rocks to prototype and build your own computer, cellular automata, 1-bit art, etc.
+
+=> ./img/screenshot_darena.png screenshot of the game. it shows a square clear space inside a textured world. inside the square there are several round rocks of two possible colors. there is a small platform, and a person.
+
+what will you do with the sand?
+
+# about
+
+darena was developed as an exercise to learn about the
+
+=> https://wiki.xxiivv.com/site/uxn.html uxn virtual machine and assembly language
+
+as part of the {s-camino} practice.
+
+=> ./s-camino.gmi {s-camino}
+
+# features
+
+* a character that moves in all four cardinal directions
+* rocks that can be pushed around, unless they are colliding with other rocks or the borders of the "arena"
+* a toggling station where rocks can be switched to the other color
+* realistic animation: the character slows down when pushing rocks, recovering their original speed when walking
+
+# controls
+
+use the arrow keys for cartesian movement within the space
+
+# possible "improvements"
+
+* add an "official" pulling option (you can pull rocks right now, but in a hacky way)
+* save rocks state (position and color) to file
+* optimize the use of memory for rock colors, using one bit per rock instead of one byte
+
+# the code
+
+this iteration has 31 rocks and a single toggling station where one can switch their color/state.
+
+last updated: sjm-1659d3 (changed JNZ to JCN)
+
+you can also find the code in the
+=> https://git.sr.ht/~rabbits/uxn/log/master/item/projects/demos/darena.usm uxn repo
+
+
+
+```darena.usm
+( darena.usm )
+( an open-ended game of rocks and sand )
+( cc0 sejo 12021 )
+
+%DEBUG { .Console/byte DEO #0a .Console/char DEO }
+
+=> ./ .Console/byte DEO #0a .Console/char DEO .gmi { .Console/byte DEO #0a .Console/char DEO }
+%DEBUG2 { .Console/short DEO2 #0a .Console/char DEO }
+
+=> ./ .Console/short DEO2 #0a .Console/char DEO .gmi { .Console/short DEO2 #0a .Console/char DEO }
+
+( parameters )
+%nrocks { #1f }
+
+=> ./ #1f .gmi { #1f }
+%nrocks-1 { #1e }
+
+=> ./ #1e .gmi { #1e }
+%nrocks_mask { #1f }
+
+=> ./ #1f .gmi { #1f }
+%minposx { #0f }
+
+=> ./ #0f .gmi { #0f }
+%minposy { #0f }
+
+=> ./ #0f .gmi { #0f }
+%maxposx { #f1 }
+
+=> ./ #f1 .gmi { #f1 }
+%maxposy { #f1 }
+
+=> ./ #f1 .gmi { #f1 }
+%anispeedmask_normal { #03 }
+
+=> ./ #03 .gmi { #03 }
+%anispeedmask_slow { #07 }
+
+=> ./ #07 .gmi { #07 }
+
+%c_color_normal { #33 }
+
+=> ./ #33 .gmi { #33 }
+%c_color_flipx { #73 }
+
+=> ./ #73 .gmi { #73 }
+%index_norock { #ff }
+
+=> ./ #ff .gmi { #ff }
+
+( output macros )
+%out_screen_x { LDA #00 SWP .Screen/x DEO2 } ( ;addr )
+
+=> ./ LDA #00 SWP .Screen/x DEO2 .gmi { LDA #00 SWP .Screen/x DEO2 }
+%out_screen_y { LDA #00 SWP .Screen/y DEO2 } ( ;addr )
+
+=> ./ LDA #00 SWP .Screen/y DEO2 .gmi { LDA #00 SWP .Screen/y DEO2 }
+
+( helper macros )
+%get_bit_n { SFT #01 AND }
+
+=> ./ SFT #01 AND .gmi { SFT #01 AND }
+%get_nibble_h { #04 SFT #0f AND }
+
+=> ./ #04 SFT #0f AND .gmi { #04 SFT #0f AND }
+%get_nibble_l { #0f AND }
+
+=> ./ #0f AND .gmi { #0f AND }
+
+%is_bit_n_set { get_bit_n #01 EQU }
+
+=> ./ get_bit_n #01 EQU .gmi { get_bit_n #01 EQU }
+
+%set_animate { #01 ;c_state LDA ORA ;c_state STA }
+
+=> ./ #01 ;c_state LDA ORA ;c_state STA .gmi { #01 ;c_state LDA ORA ;c_state STA }
+%rst_animate { #00 ;c_state STA }
+
+=> ./ #00 ;c_state STA .gmi { #00 ;c_state STA }
+
+( devices )
+
+|00 @System [ &vector $2 &wst $1 &rst $1 &pad $4 &r $2 &g $2 &b $2 ]
+|10 @Console [ &pad $8 &char $1 &byte $1 &short $2 &string $2 ]
+|20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &color $1 ]
+|80 @Controller [ &vector $2 &button $1 &key $1 ]
+
+( variables )
+
+|0000
+
+@c_pos [ &x $1 &y $1 ] ( character position )
+@c_speed [ &x $1 &y $1 ] ( character speed )
+@c_color [ $1 ] ( character color )
+@c_sprite [ $2 ] ( character sprite addr )
+@c_state [ $1 ] ( high_nibble: animation pointer, bit0: is_animated )
+
+@f_count [ $1 ] ( frame counter )
+@ani_speedmask [ $1 ] ( animation speed mask )
+
+@r_speed_x [ $f ]
+@r_speed_y [ $f ]
+
+@tog [ &x $1 &y $1 &state $1 ] ( toggle station state )
+
+( program )
+
+|0100 @reset ( -> )
+ #f396 .System/r DEO2
+ #e263 .System/g DEO2
+ #9030 .System/b DEO2
+
+ ;on_frame .Screen/vector DEO2
+
+ ( init character )
+ #50 ;c_pos/x STA
+ #10 ;c_pos/y STA
+ #00 ;c_speed/x STA
+ #00 ;c_speed/y STA
+ c_color_normal ;c_color STA
+ ;s_monitx_stepfront0 ;c_sprite STA2
+ rst_animate
+
+ anispeedmask_normal ;ani_speedmask STA
+
+ ( init toggler )
+ #27 ;tog/x STA
+ #27 ;tog/y STA
+ #00 ;tog/state STA
+
+
+ ( init background )
+ ;init_bg JSR2
+BRK
+
+
+@on_frame ( -> )
+ ;f_count LDA #01 ADD DUP ;f_count STA ( increase frame counter )
+ ;ani_speedmask LDA ( mask with animation speed mask )
+ AND #00 EQU ,update_frame JCN ( jump to update if it's time )
+BRK
+
+@update_frame
+ ( check keyboard )
+ ;check_keys JSR2
+
+ ( animate character sprite )
+ ;animate_c JSR2
+
+ ( clear sprites )
+ ;clear JSR2
+
+ ( update character vars )
+ ;update_c/run JSR2
+
+ ( update rocks + stand )
+ ;update_r/run JSR2
+
+ ( draw )
+ ;draw JSR2
+
+BRK
+
+@clear
+ ( clear rocks )
+ ;s_clear .Screen/addr DEO2
+
+ nrocks #00
+ &rocks_loop
+ DUP ( get rocks_x[i] )
+ ;rocks_x ROT #00 SWP ADD2 out_screen_x
+
+ DUP ( get rocks_y[i] )
+ ;rocks_y ROT #00 SWP ADD2 out_screen_y
+
+ #30 .Screen/color DEO
+
+ #01 ADD
+ DUP2
+ NEQ ,&rocks_loop JCN
+ POP2
+
+ ( clear character )
+ ;clear_c JSR2
+JMP2r
+
+@draw
+ ( draw toggler )
+
+ ;tog/x out_screen_x
+ ;tog/x out_screen_y
+ ;s_stand .Screen/addr DEO2
+ #23 .Screen/color DEO
+
+ ( draw rocks )
+ ;s_bola .Screen/addr DEO2
+
+ nrocks #00
+
+ &rocks_loop
+ DUP ( get rocks_x[i] )
+ ;rocks_x ROT #00 SWP ADD2 out_screen_x
+
+ DUP ( get rocks_y[i] )
+ ;rocks_y ROT #00 SWP ADD2 out_screen_y
+
+ ( DUP ( get color bitwise ) )
+ ( ;r_color LDA SWP get_bit_n #31 ADD .Screen/color DEO )
+
+ DUP
+ ;r_color ROT #00 SWP ADD2 LDA #31 ADD .Screen/color DEO
+
+ #01 ADD
+
+ DUP2
+ NEQ ,&rocks_loop JCN
+ POP2
+
+ ( draw character )
+ ;draw_c JSR2
+JMP2r
+
+@check_keys
+ #00 ;c_speed/x STA
+ #00 ;c_speed/y STA
+
+ .Controller/button DEI #07 is_bit_n_set ,&der JCN
+ .Controller/button DEI #06 is_bit_n_set ,&izq JCN
+ .Controller/button DEI #05 is_bit_n_set ,&aba JCN
+ .Controller/button DEI #04 is_bit_n_set ,&arr JCN
+
+ rst_animate
+
+ JMP2r
+
+ &der
+ #01 ;c_speed/x STA
+ set_animate
+ c_color_normal ;c_color STA
+ ;s_monitx_stepside0 ;c_sprite STA2
+ JMP2r
+
+ &izq
+ #ff ;c_speed/x STA
+ set_animate
+ c_color_flipx ;c_color STA
+ ;s_monitx_stepside0 ;c_sprite STA2
+ JMP2r
+
+ &aba
+ #01 ;c_speed/y STA
+ set_animate
+ c_color_normal ;c_color STA
+ ;s_monitx_stepfront0 ;c_sprite STA2
+ JMP2r
+
+ &arr
+ #ff ;c_speed/y STA
+ set_animate
+ c_color_normal ;c_color STA
+ ;s_monitx_stepback0 ;c_sprite STA2
+ JMP2r
+
+ &end
+JMP2r
+
+( sub-routines )
+
+( in: sourcex, source y, index, rangex, rangey )
+( puts in the stack the index of rock collisioned with )
+@collision_rocks
+ &range_y $1
+ &range_x $1
+ &src_i $1
+ &src_x $1
+ &src_y $1
+
+ &rock_x $1
+ &rock_y $1
+
+ &run
+ ,&range_y STR
+ ,&range_x STR
+ ,&src_i STR
+ ,&src_y STR
+ ,&src_x STR
+
+ ( check collision with rocks )
+ ( nrocks #00 )
+ ,&src_i LDR nrocks_mask AND DUP #01 ADD nrocks_mask AND
+
+ &rocks_loop
+ DUP ( get rocks_x[i] )
+ ;rocks_x ROT #00 SWP ADD2 LDA ,&rock_x STR
+
+ DUP ( get rocks_y[i] )
+ ;rocks_y ROT #00 SWP ADD2 LDA ,&rock_y STR
+
+ ,&src_x LDR ,&rock_x LDR ,&range_x LDR SUB GTH ( if sx > rx - 8 )
+ ,&src_x LDR ,&rock_x LDR ,&range_x LDR ADD LTH ( if sx < rx + 8 )
+ ,&src_y LDR ,&rock_y LDR ,&range_y LDR SUB GTH ( if sy > ry - 8 )
+ ,&src_y LDR ,&rock_y LDR ,&range_y LDR ADD LTH ( if sy < ry + 8 )
+ ADD ADD ADD #04 EQU ,&found JCN
+
+ #01 ADD nrocks_mask AND
+ DUP2
+ NEQ ,&rocks_loop JCN
+ POP2
+ #ff
+ JMP2r
+ &found
+ SWP POP ( remove loop limit )
+ DUP ;&src_i LDA NEQ ,&end JCN ( check if result is the same as index )
+ POP #ff
+ JMP2r
+
+ &end
+
+JMP2r
+
+@update_c ( update character position )
+ &new_x $1
+ &new_y $1
+
+ &rock_i $1
+ &rock_x $1
+ &rock_y $1
+
+
+ &run
+ ;c_speed/x LDA ;c_pos/x LDA ADD
+ ,&new_x STR
+ ;c_speed/y LDA ;c_pos/y LDA ADD
+ ,&new_y STR
+
+ anispeedmask_normal ;ani_speedmask STA
+
+ &check_x
+ ( check collision with borders )
+ ,&new_x LDR minposx EQU ;&noup_x JCN2
+ ,&new_x LDR maxposx EQU ;&noup_x JCN2
+
+
+ ( check collision with rocks )
+ ,&new_x LDR ,&new_y LDR index_norock #09 #06
+ ;collision_rocks/run JSR2
+
+ ( if it is colliding with rock, check further )
+ DUP #ff NEQ ,&check_x_collision JCN
+ POP
+ ,&update_x JMP
+
+ &check_x_collision
+ ( DUP DEBUG )
+ ( slow down and save rock index )
+ anispeedmask_slow ;ani_speedmask STA
+ ,&rock_i STR
+
+ ( check if rock collides with others )
+ ;rocks_x #00 ,&rock_i LDR ADD2 LDA ,&rock_x STR
+ ;rocks_y #00 ,&rock_i LDR ADD2 LDA ,&rock_y STR
+
+ ,&rock_x LDR ,&rock_y LDR ,&rock_i LDR #09 #06
+ ;collision_rocks/run JSR2
+
+ ( DUP DEBUG )
+
+ ( if it is colliding, then skip adding x )
+ DUP #ff NEQ ,&check_y JCN
+ POP
+
+
+ ( if not, check for borders )
+ ;&rock_x LDA minposx EQU ;&noup_x JCN2
+ ;&rock_x LDA maxposx EQU ;&noup_x JCN2
+
+ ( move rock with same speed as c )
+ ;&rock_x LDA ;c_speed/x LDA ADD
+ ;rocks_x #00 ;&rock_i LDA ADD2
+ STA
+
+
+ &update_x
+ ;&new_x LDA ;c_pos/x STA
+
+ ,&check_y JMP
+
+ &noup_x
+
+ &check_y
+ ( check collision with borders )
+ ;&new_y LDA minposy EQU ;&noup_y JCN2
+ ;&new_y LDA maxposy EQU ;&noup_y JCN2
+
+ ( check collision with rocks )
+ ;&new_x LDA ;&new_y LDA index_norock #06 #09
+ ;collision_rocks/run JSR2
+
+ ( if it is colliding with rock, check further )
+ DUP #ff NEQ ,&check_y_collision JCN
+ POP
+ ,&update_y JMP
+
+ &check_y_collision
+ ( DUP DEBUG )
+ anispeedmask_slow ;ani_speedmask STA
+ ;&rock_i STA
+
+ ( check if rock collides with others )
+ ;rocks_x #00 ;&rock_i LDA ADD2 LDA ;&rock_x STA
+ ;rocks_y #00 ;&rock_i LDA ADD2 LDA ;&rock_y STA
+
+ ;&rock_x LDA ;&rock_y LDA ;&rock_i LDA #06 #09
+ ;collision_rocks/run JSR2
+
+ ( DUP DEBUG )
+
+ ( if it is colliding, then skip adding y )
+ DUP #ff NEQ ,&noup_y JCN
+ POP
+
+ ( if not, check for borders )
+ ;&rock_y LDA minposx EQU ;&noup_y JCN2
+ ;&rock_y LDA maxposx EQU ;&noup_y JCN2
+
+ ( if not colliding, then move rock with same speed as c )
+ ;&rock_y LDA ;c_speed/y LDA ADD
+ ;rocks_y #00 ;&rock_i LDA ADD2
+ STA
+
+
+ &update_y
+ ;&new_y LDA ;c_pos/y STA
+ JMP2r
+
+ &noup_y
+JMP2r
+
+@update_r
+ &rock_i $1
+
+ &run
+
+ ( check collision with rocks )
+ ;tog/x LDA ;tog/y LDA index_norock #02 #02
+ ;collision_rocks/run JSR2
+
+ ( if it is colliding with rock, check if it needs to change state )
+ DUP #ff NEQ ,&change_state JCN
+
+ ( DUP DEBUG )
+
+ ( if there's no collision, reset toggler )
+ POP
+ #00 ;tog/state STA
+ JMP2r
+
+ &change_state
+ ( DUP DEBUG )
+ ,&rock_i STR
+ ;tog/state LDA ,&done JCN ( don't toggle if state is active )
+
+ ;r_color #00 ,&rock_i LDR ADD2 DUP2 STH2
+ LDA #01 EOR STH2r STA
+ #01 ;tog/state STA
+ &done
+
+JMP2r
+
+@animate_c
+ ( is bit0 -animate- on? )
+ ;c_state LDA DUP #00 get_bit_n #01 NEQ ,&s_no_animate JCN
+
+ ( increment and save animation pointer )
+ &s_animate
+ DUP
+ get_nibble_h #01 ADD #03 AND #40 SFT
+ SWP get_nibble_l ORA
+ ;c_state STA
+ JMP2r
+
+ &s_no_animate
+ get_nibble_h #0f AND ;c_state STA
+JMP2r
+
+@draw_c ( draw character )
+ #00 ;c_state LDA get_nibble_h #08 MUL
+ ;c_sprite LDA2 ADD2 .Screen/addr DEO2
+ ;c_pos/x out_screen_x
+ ;c_pos/y out_screen_y
+ ;c_color LDA .Screen/color DEO
+JMP2r
+
+@clear_c ( clear character )
+ ;s_clear .Screen/addr DEO2
+ ;c_pos/x out_screen_x
+ ;c_pos/y out_screen_y
+ #30 .Screen/color DEO
+JMP2r
+
+@init_bg
+ ( init bg )
+ ;s_border .Screen/addr DEO2
+
+ .Screen/height DEI2 #0000 STH2
+ &vertical0loop
+ DUP2
+ STH2r
+ DUP2 .Screen/y DEO2
+
+
+ .Screen/width DEI2 #0000 STH2
+ &horizontal0loop
+ DUP2
+ STH2r
+ DUP2 .Screen/x DEO2
+
+ #23 .Screen/color DEO
+
+ #0008 ADD2 DUP2 STH2
+ GTH2 ,&horizontal0loop JCN
+
+ STH2r POP2 POP2
+
+
+ #0008 ADD2 DUP2 STH2
+ GTH2 ,&vertical0loop JCN
+ STH2r
+ POP2 POP2
+
+ ( arena )
+
+ ;s_clear .Screen/addr DEO2
+
+ #00 maxposy #00 minposy STH2
+ &vertical0loop_clear
+ DUP2
+ STH2r
+ DUP2 .Screen/y DEO2
+
+
+ #00 maxposx #00 minposx STH2
+ &horizontal0loop_clear
+ DUP2
+ STH2r
+ DUP2 .Screen/x DEO2
+
+ #20 .Screen/color DEO
+
+ #0008 ADD2 DUP2 STH2
+ GTH2 ,&horizontal0loop_clear JCN
+
+ STH2r POP2 POP2
+
+ #0008 ADD2 DUP2 STH2 GTH2 ,&vertical0loop_clear JCN
+ STH2r
+ POP2 POP2
+
+JMP2r
+
+( rocks )
+@rocks_x [ 25 30 42 50 67 90 98 e8 20 43 43 57 5a 7f bc a5
+ e5 dd a2 20 b7 9b 38 e8 33 43 63 b7 aa cf bc ]
+@rocks_y [ 60 48 34 56 23 65 65 65 ba e9 24 22 72 91 22 c5
+ 25 30 42 50 67 90 98 e8 20 43 43 57 5a 7f bc ]
+@r_color [ 00 01 01 00 00 00 01 01 01 01 00 00 01 01 00 00
+ 01 00 01 00 00 01 00 01 01 01 01 01 00 00 00 ]
+
+
+( sprites )
+
+@s_clear [ 0000 0000 0000 0000 ]
+@s_border [ 3288 7e83 780d e013 ]
+@s_bola [ 3c4e 9ffd f962 3c00 ]
+@s_stand [ 0000 0000 0024 7eff ]
+@s_stand_original [ 0000 0000 0000 3c7e ]
+
+@s_monitx [ 3c7e 5a7f 1b3c 5a18 ]
+@s_monitx_back [ 3c7e 7efe d83c 5a18 ]
+
+@s_monitx_stepfront0 [ 3c7e 5a7f 1b3c 5a18 ]
+@s_monitx_stepfront1 [ 3c7e 5a7f 1b3c 5a10 ]
+@s_monitx_stepfront2 [ 3c7e 5a7f 1b3c 5a18 ]
+@s_monitx_stepfront3 [ 3c7e 5a7f 1b3c 5a08 ]
+
+@s_monitx_stepback0 [ 3c7e 7efe d83c 5a18 ]
+@s_monitx_stepback1 [ 3c7e 7efe d83c 5a10 ]
+@s_monitx_stepback2 [ 3c7e 7efe d83c 5a18 ]
+@s_monitx_stepback3 [ 3c7e 7efe d83c 5a08 ]
+
+@s_monitx_stepside0 [ 1c3c 7afc d81c 1818 ]
+@s_monitx_stepside1 [ 1c3c 7afc d81c 1828 ]
+@s_monitx_stepside2 [ 1c3c 7afc d81c 3810 ]
+@s_monitx_stepside3 [ 1c3c 7afc d81c 1814 ]
+```
+
+enlaza aquí {s-camino}
+
+=> ./s-camino.gmi {s-camino}
+
+página actualizada en: sejmana-1660, día 1 (12021-05-20)
diff --git a/gem/ffmpeg.gmi b/gem/ffmpeg.gmi
new file mode 100644
index 0000000..cb83374
--- /dev/null
+++ b/gem/ffmpeg.gmi
@@ -0,0 +1,114 @@
+# apuntes de ffmpeg
+
+notas de usos comunes que le doy a ffmpeg
+
+# "trim" / cortar
+
+```
+ffmpeg -i input.video -ss 5 -t 20 output.video
+```
+
+donde:
+-ss es el tiempo inicial
+-t es la duracion total del nuevo video
+
+
+# escalar
+
+```
+ffmpeg -i input.video -vf scale=640:480 output.video
+```
+
+y para reducir el tamaño del archivo, suele ser útil recomprimir con crf (constant rate factor)
+
+```
+ffmpeg -i input.video -crf 24 output.video
+```
+
+en teoría 24 es una compresión difícil de percibir. números mayores comprimen más.
+
+# cambio de framerate
+
+```
+ffmpeg -i input.video -r 30 output.video
+```
+
+o
+
+```
+ffmpeg -i input.video -filter:v fps=fps=30 output.video
+```
+
+# cambio de "velocidad"
+
+obtiene un video a 2x de velocidad:
+
+```
+ffmpeg -i input.video -filter:v "setpts=0.5*PTS" output.video
+```
+
+para hacer 60x (por ejemplo, convertir minutos a segundos):
+
+```
+ffmpeg -i input.video -filter:v "setpts=0.016*PTS" output.video
+```
+
+# concatenar
+
+hacer lista de videos con el formato:
+
+```
+file 'archivo1'
+file 'archivo2'
+file 'archivo3'
+```
+y luego:
+
+```
+ffmpeg -f concat -i lista.txt -c copy output.video
+```
+
+
+# generar video desde serie de img
+
+```
+ffmpeg -framerate 30 -i frame-%04d.tif -pix_fmt yuv420p -c:v libx264 <output.mp4>
+```
+
+# crop (y exportar desde recordmydesktop)
+
+```
+ffmpeg -i out.ogv -filter:v "crop=1280:720:0:0" -codec:v libx264 -codec:a libmp3lame output.mp4
+```
+
+
+# video a partir de una imagen
+
+```
+# video de una imagen,
+# 10 segundos, 30 frames por segundo
+ffmpeg -loop 1 \
+ -i imagen_verde.png \
+ -t 00:00:10 -r 30 \
+ video_verde.ogv
+```
+
+# video a partir de serie de imágenes
+
+```
+# cambia entre imágenes a 2fps,
+# video final a 30fps
+ffmpeg -framerate 2 \
+ -i "%02d.png" \
+ -pix_fmt yuv420p \
+ -c:v libx264 \
+ -r 30 salida.mp4
+```
+
+# overlay de imagen sobre video
+
+```
+ffmpeg -i input.mp4 -i imagen.png -filter_complex "overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2" output.mp4
+```
+
+página actualizada en: sejmana-1660, día 1 (12021-05-20)
diff --git a/gem/imagemagick.gmi b/gem/imagemagick.gmi
new file mode 100644
index 0000000..50e69c6
--- /dev/null
+++ b/gem/imagemagick.gmi
@@ -0,0 +1,118 @@
+# apuntes de imagemagick
+
+# redimensiona imagen
+
+```
+convert imagen.png -resize 100x100 imagen100.png
+```
+
+o con -scale, para no interpolar y mantener la apariencia de pixeles
+
+```
+convert imagen.png -scale 200% imagenx2.png
+```
+
+# reemplaza color por otro
+
+reemplaza azul por blanco:
+
+```
+convert imagen.png -fill white -opaque blue salida.png
+```
+
+se puede agregar fuzz factor:
+
+```
+convert imagen.png -fuzz 45% -fill white -opaque blue salida.png
+```
+
+y para convertir a transparente:
+
+```
+convert imagen.png -fuzz 45% -transparent blue salida.png
+```
+
+# elimina metadatos exif
+
+para imágenes jpg
+
+```
+convert foto.jpg -strip fotolimpia.jpg
+```
+
+esto re-comprime la imagen, pero puede usarse al mismo tiempo que se redimensiona
+
+```
+convert foto.jpg -strip -resize 640x480 fotolimpia_480p.jpg
+```
+
+# convierte pdf
+
+por default la conversión sucede en baja calidad, esto la mejora:
+
+```
+convert imagen.png -quality 100 -units PixelsPerInch -density 300x300 imagen.pdf
+```
+
+y para el caso opuesto:
+
+```
+convert -quality 100 -units PixelsPerInch -density 300x300 imagen.pdf imagen.png
+```
+
+# reduce la cantidad de colores
+
+deja que imagemagick elija qué colores utilizar:
+
+```
+convert imagen.png -colors 8 imagen_8.png
+```
+
+o con dithering:
+
+```
+convert imagen.png -dither FloydSteinberg -colors 8 imagen_8.png
+```
+
+en -dither se puede usar None, Riemersma, o FloydSteinberg
+
+
+# genera mapas de bits
+
+con color plano:
+
+```
+convert -size 100x100 xc:'rgb(0,255,0)' imagen_verde.png
+```
+
+con ruido:
+
+```
+convert -size 100x100 xc: +noise Random imagen_ruido.png
+```
+
+# compone/encima imágenes
+
+para componer una imagen con fondo transparente sobre otra que se convertirá en su fondo
+
+```
+composite -gravity center imagen_con_alpha.png fondo.png resultado.png
+```
+
+# corta
+
+para cortar una imagen a ciertas dimensiones (wxh) y cierto offset en x,y
+
+```
+convert imagen.png -crop 300x300+100+50 +repage recorte.png
+```
+
+
+para quitarte el borde de color constante a una imagen
+
+```
+convert imagen.png -trim +repage sinborde.png
+```
+
+
+página actualizada en: sejmana-1660, día 1 (12021-05-20)
diff --git a/gem/index.gmi b/gem/index.gmi
new file mode 100644
index 0000000..b2a2d2f
--- /dev/null
+++ b/gem/index.gmi
@@ -0,0 +1,14 @@
+# ¿queso de mango?
+
+cuaderno en proceso de almacenar y compartir notas variadas, con miras a que tengan (más) vida al vibrar en la red…
+
+notebook in progress, saving and sharing various materials, trying to give them (networked) life.
+
+=> ./compudanzas.gmi {compudanzas}
+=> ./coloring_computers.gmi {coloring computers}
+=> ./s-camino.gmi {s-camino}
+=> ./darena.gmi {darena}
+=> ./recetas.gmi {recetas}
+=> ./indice.gmi {índice}
+
+página actualizada en: sejmana-1660, día 1 (12021-05-20)
diff --git a/gem/indice.gmi b/gem/indice.gmi
new file mode 100644
index 0000000..c88bd02
--- /dev/null
+++ b/gem/indice.gmi
@@ -0,0 +1,14 @@
+# índice de páginas
+
+=> ./avr-asm.gmi {avr-asm}
+=> ./coloring_computers.gmi {coloring computers}
+=> ./compudanzas.gmi {compudanzas}
+=> ./danzasistemas-tag.gmi {danzasistemas-tag}
+=> ./darena.gmi {darena}
+=> ./ffmpeg.gmi {ffmpeg}
+=> ./imagemagick.gmi {imagemagick}
+=> ./logiteca.gmi {logiteca}
+=> ./recetas.gmi {recetas}
+=> ./s-camino.gmi {s-camino}
+
+página actualizada en: sejmana-1660, día 1 (12021-05-20)
diff --git a/gem/logiteca.gmi b/gem/logiteca.gmi
new file mode 100644
index 0000000..891aa7d
--- /dev/null
+++ b/gem/logiteca.gmi
@@ -0,0 +1,290 @@
+# logiteca
+
+compendio de circuitos lógicos que pueden implementarse en las "danzas compuertas".
+
+material de referencia para las {compudanzas}
+
+=> ./compudanzas.gmi {compudanzas}
+
+# acerca de
+
+este es un compendio de circuitos lógicos que pueden implementarse en las "danzas compuertas".
+
+están descritos en *verilog*, un lenguaje descriptor de hardware. esto con la idea de estandarizarlos, de facilitar simularlos e implementarlos en otros materiales, y de indicar su cualidad de *red abstracta*.
+
+utilizamos el lenguaje a nivel de compuertas lógicas solamente: cada compuerta se expresa como una función (`and()`, `not()`, `or()`, `nor()`, `nand()`, etc) donde el primer argumento es el nombre de la *salida* de la compuerta, y el o los otros argumentos son los nombres de las *entradas*.
+
+el número de participantes asignado por circuito está contado como el *número de entradas* más el *número de compuertas*, donde alguna(s) de ella(s) incluyen las compuertas cuyas salidas son también la(s) del circuito. si se tienen más participantes, se pueden agregar el *número de salidas*: persona(s) que copien el resultado de la compuerta correspondiente.
+
+# multiplicador de 1 bit
+
+circuito que multiplica a dos números de 1 bit y da el resultado en 1 bit.
+
+## multiplicador de 1 bit con compuertas habituales (3 o 4 participantes)
+
+```
+// multiplicador construido con compuertas habituales
+// entradas (2): a,b
+// salidas (1): r (resultado)
+// compuertas (1): 1 de 2 entradas
+
+module multiplicador( a, b, r);
+
+input wire a, b;
+output wire r;
+
+and C1(r, a, b);
+
+endmodule
+```
+
+## multiplicador de 1 bit con nor (5 o 6 participantes)
+
+```
+// multiplicador construido con nor's
+// entradas (2): a,b
+// salidas (1): r (resultado)
+// compuertas (3): 2 de 1 y 1 de 2 entradas
+
+module multiplicador( a, b, r);
+
+input wire a, b;
+output wire r;
+wire p1,p2;
+
+// negadas
+nor C1(p1, a);
+nor C2(p2, b);
+
+// resultado
+nor C3(r, p1, p2);
+
+endmodule
+```
+
+# contadores
+
+circuitos que incrementan 1 al número binario colocado en la entrada, con el mismo número de bits a la entrada que a la salida.
+
+si la salida se "conecta" a la entrada, entonces con cada paso se obtiene el
+número siguiente en la secuencia, es decir se "cuenta".
+
+al llegar al último número, se regresa a 0.
+
+## contador de 2 bits con compuertas habituales (4 o 6 participantes)
+
+```
+// contador de 2 bits con compuertas habituales
+// entradas (2): a, b
+// salidas (2): x, y
+// compuertas (2): 1 de 1 y 1 de 2 entradas
+
+module contador(a, b, x, y);
+
+input wire a,b;
+output wire x,y;
+
+not C1(y, b);
+xor C2(x, a,b);
+
+endmodule
+```
+
+## contador de 2 bits con nor (7 o 9 participantes)
+
+```
+// contador de 2 bits con nor
+// entradas (2): a, b
+// salidas (2): x, y
+// compuertas (5): 2 de 1 y 3 de 2 entradas
+
+module contador(a, b, x, y);
+
+input wire a,b;
+output wire x,y;
+wire p1, p2, p3;
+
+// negaciones
+nor C1(y, b);
+nor C2(p1, a);
+
+// para x
+nor C3(p2, a,b);
+nor C4(p3, y,p1);
+nor C5(x, p2,p3);
+
+endmodule
+```
+
+
+## contador de 3 bits con nor (13 o 16 participantes)
+
+```
+// contador de 3 bits con compuertas habituales
+// entradas (3): a, b, c
+// salidas (3): x, y, z
+// compuertas (10): 3 de 1, 4 de 2, 3 de 3 entradas
+
+module contador(a, b, c, x, y, z);
+
+input wire a,b,c;
+output wire x,y,z;
+wire p1, p2, p3, p4, p5, p6, p7;
+
+// negaciones
+nor C1(p1, a);
+nor C2(p2, b);
+nor C3(z, c);
+
+// para y
+nor C4(p3, b,c);
+nor C5(p4, p2,z);
+nor C6(y, p3,p4);
+
+// para x
+nor C7(p5, a,b);
+nor C8(p6, p1, p2, z);
+nor C9(p7, a, p2, c);
+nor C10(x, p5, p6, p7);
+
+endmodule
+```
+
+
+# half adder
+
+circuito que suma dos bits y da el resultado en dos bits (resultado y *carry*)
+
+## half adder con compuertas habituales (4 o 6 participantes)
+
+```
+// half adder construido con compuertas habituales
+// entradas (2): a,b
+// salidas (2): r, c (resultado, carry)
+// compuertas (2): 2 de 2 entradas
+
+module halfadder( a, b, r, c);
+
+input wire a, b;
+output wire r,c;
+
+// carry
+and C1(c, a, b);
+
+// resultado
+xor C2(r, a, b);
+
+endmodule
+```
+
+## half adder usando nor (7 o 9 participantes)
+
+```
+// half adder construido usando nor's
+// entradas (2): a,b
+// salidas (2): r, c (resultado, carry)
+// compuertas (5): 2 de 1 y 3 de 2 entradas
+
+module halfadder( a, b, r, c);
+
+input wire a, b;
+output wire r,c;
+wire p1,p2,p3;
+
+// negadas
+nor C1(p1, a);
+nor C2(p2, b);
+
+// carry
+nor C3(c, p1, p2);
+
+// resultado
+nor C4(p3, a, b);
+nor C5(r, c, p3);
+
+endmodule
+```
+
+
+# full adder
+
+circuito que suma tres bits y da el resultado en dos bits (resultado y *carry*).
+
+## full adder con compuertas habituales (14 o 16 participantes)
+
+```
+// full adder construido con compuertas habituales
+// entradas (3): a, b, c
+// salidas (2): carry, r (resultado)
+// compuertas (11): 2 de 1 y 9 de 2 entradas
+
+module fulladder( a, b, c, r, carry);
+
+input wire a, b, c;
+output wire r, carry;
+wire p1, p2, p3, p4, p5, p6, p7, p8, p9;
+
+// negadas
+not C1(p1, a);
+not C2(p3, p2);
+
+// diferencias b,c
+xor C3(p2, b, c);
+or C4(p4, b, c);
+and C5(p5, b, c);
+
+// armado de resultado
+and C6(p6, p1, p2);
+and C7(p7, a, p3);
+or C8(r, p6, p7);
+
+// armado de carry
+and C9(p8, p1, p5);
+and C10(p9, a, p4);
+or C11(carry, p8, p9);
+
+endmodule
+```
+
+## full adder usando nor (15 o 17 participantes)
+
+```
+// full adder construido usando nor's
+// entradas (3): a, b, c
+// salidas (2): carry, r (resultado)
+// compuertas (12): 3 de 1, 3 de 2, 4 de 3 y 1 de 4 entradas
+
+module fulladder( a, b, c, r, carry);
+
+input wire a, b, c;
+output wire r, carry;
+wire p1, p2, p3, p4, p5, p6, p7, p8, p9, p10;
+
+// negadas
+nor C1(p1, a);
+nor C2(p2, b);
+nor C3(p3, c);
+
+// pa'l carry
+nor C4(p4, a, b);
+nor C5(p5, a, c);
+nor C6(p6, b, c);
+
+// pa resultado
+nor C7(p7, a, b , c);
+nor C8(p8, p1, b, p3);
+nor C9(p9, a, p2, p3);
+nor C10(p10, p1, p2, c);
+
+// salidas
+nor C11(carry, p4, p5, p6);
+nor C12(r, p7, p8, p9, p10);
+
+endmodule
+```
+
+enlaza aquí {compudanzas}
+
+=> ./compudanzas.gmi {compudanzas}
+
+página actualizada en: sejmana-1660, día 1 (12021-05-20)
diff --git a/gem/recetas.gmi b/gem/recetas.gmi
new file mode 100644
index 0000000..9318b41
--- /dev/null
+++ b/gem/recetas.gmi
@@ -0,0 +1,194 @@
+# recetas veganas
+
+# hotcakes de chocolate
+
+~35 min
+~10-12 piezas
+
+(remix de sejo y mel* de la receta en pag 46 del libro "cocinar vegano vol.1" de francesca carpinelli cocinavegano.com)
+
+## ingredientes
+
+* 2 tazas avena (hojuela de grano entero, "old-fashioned")
+* 1.5 tazas leche de soya
+* 1 cdita polvo para hornear
+* 1 cdita bicarbonato de sodio
+* 1 cdita canela en polvo
+* 1/2 cdita sal de mar
+* 3 cdas azucar mascabado
+* 2 cdas cocoa en polvo
+* 1 cda extracto de vainilla
+* 1 cdita aceite de coco (u otro)
+* 1/2 taza chocolate amargo en trozos (opcional)
+
+## instrucciones
+
+* muele la avena hasta hacerla harina
+* agrega el polvo para hornear, bicarbonato de sodio, sal, canela, cocoa y azucar
+* mezcla bien
+* poco a poco agrega leche de soya y bate hasta incorporar los ingredientes
+* agrega el extracto de vainilla y bate de nuevo
+* coloca sarten a fuego medio
+* cuando se caliente, aceita y sirve la mezcla en partes iguales
+* cuando se hagan burbujas en la superficie, agrega trozos de chocolate y voltea
+* retira cuando tengan la consistencia que te agrade
+
+(recuerda que no hay ingredientes crudos en la receta por lo que no hay riesgos por si parece que algo falta de cocerse)
+
+## sugerencia
+
+sirve con frutos rojos, moras, platano, mermeladas, mantequilla de cacahuate y/o de almendra.
+
+
+# "leche" y "queso" de soya
+
+preparar "leche" de soya resulta en restos llamados "okara", que puede usarse entre otras cosas para preparar un "queso"
+
+~60 min
+~1 lt de leche y
+un queso de ~120 gr
+
+## ingredientes
+
+solo para la "leche":
+
+* 1/2 taza frijol de soya seco
+* 4 tazas agua
+
+para el queso:
+
+* 2 cditas levadura nutricional
+* 1/2 cdita sal
+* 1/2 limón
+* 1 chorrito aceite de oliva
+* 3 tazas agua
+
+necesitas alguna herramienta para licuar/moler, y otra para colar finamente (e.g. manta de cielo)
+
+dos ollas y algunos recipientes, y un colador ayuda
+
+## instrucciones
+
+### previo:
+
+* deja remojando el frijol de soya por unas 8 horas
+
+### durante:
+
+para el queso:
+* empieza a hervir 3 tazas de agua
+
+para la leche:
+* escurre el frijol de soya - al remojarse crece como hasta 1.5 tazas
+* muele en la licuadora el frijol con 3 tazas de agua
+* usa la manta de cielo para filtrar y exprimir el resultado dentro de una olla
+ (el liquido se vuelve la leche, y lo solido es la okara)
+* pon la olla de la leche a hervir, cuidando de quitarle la espuma y nata
+* cuando hierva, cambia a fuego medio y espera ~20 minutos, quitando espuma y
+ revolviendo en ocasiones
+* deja enfriar y bebe!
+
+para el queso:
+* tan pronto el agua hierva, y ya tengas la okara, ponla en esa olla
+* deja cocer a fuego medio durante 15-20 minutos
+* usa el colador y la manta de cielo para filtrar el resultado (el liquido ya no
+ lo usaremos, y el solido es la okara cocida)
+* deja enfriar un rato
+* cuando te sea posible, exprime para quitar todo el liquido que puedas
+* coloca la okara cocida y "seca" en un recipiente
+* sirve encima la levadura nutricional, sal, limon y aceite de oliva
+* mezcla muy bien con tus manos
+* compacta la mezcla para que sea "queso"
+* aparentemente conviene refrigerar un rato antes de comerlo
+
+
+## referencias
+
+remix de estas recetas:
+=> https://simpleveganblog.com/homemade-soy-milk/ leche de soya
+=> https://youtube.com/watch?v=BU2LEYHb_qk tofu casero (youtube)
+
+
+
+# pastel de garbanzo
+
+remix de "falafel al horno"
+
+(receta en proceso de afinarse porque la hago de manera intuitiva (?))
+
+~60 min
+~2 "pasteles"
+
+## ingredientes
+
+### para la masa
+
+* 1 taza garbanzo seco
+* 2 jitomates medianos
+* 1/2 cebolla
+* 2 dientes ajo
+* 1 cucharada sal
+* 1 cucharadita pimienta
+* 1 cucharada comino
+* 1.5 tazas agua
+* 1 cucharadita aceite
+* al gusto cilantro
+* al gusto chiles serranos
+
+### extras:
+
+* 1 cucharadita ajonjoli
+* 1 pimiento
+* 1/2 taza setas
+* 1/2 taza espinaca
+
+necesitas horno y alguna herramienta para moler/licuar
+
+## instrucciones
+
+### previo:
+
+* deja remojando los garbanzos entre 8 y 12 horas (crecen como a 2.25 tazas)
+
+### durante:
+
+* escurre y enjuaga los garbanzos
+* muele en la licuadora los garbanzos con el agua, cebolla, jitomates, ajo, sal,
+ pimienta, comino, cilantro y chile(s)
+* aceita un par de moldes para pan y sirve la mezcla en ellos
+* opcional: deja reposar en el refrigerador por ~30 minutos
+* parte los pimientos y setas en rebanaditas, coloca junto con la espinaca y
+ ajonjoli en la superficie de la masa
+* coloca los moldes en el horno, enciende a ~300 grados C
+* espera unos 40-50 minutos, o hasta que adquieran la consistencia que desees
+* apaga el horno y aprovecha el calor para seguir cociendo
+* deja enfriar y sirve!
+
+queda bien junto con limon, aguacate, y alguna salsa (en proceso de definirla)
+
+
+# kombucha
+
+(notas que uso para cada ronda)
+
+~1 lt de kombucha
+
+## ingredientes
+
+* 1/2 taza liquido iniciador + scoby
+* 1 taza agua caliente
+* 1 cucharadita te negro (o 2 sobres)
+* 1/4 taza azucar mascabado (4 cucharadas)
+* 3 tazas agua fria
+
+## instrucciones
+
+* prepara el te con el agua caliente
+* cuela las hojas del te
+* disuelve la azucar en el te
+* diluye el te con el agua fria
+* agrega la mezcla al liquido iniciador + scoby
+* tapa con tela / filtros de cafe, y espera al menos un par de semanas
+
+
+página actualizada en: sejmana-1660, día 1 (12021-05-20)
diff --git a/gem/s-camino.gmi b/gem/s-camino.gmi
new file mode 100644
index 0000000..bb5ab21
--- /dev/null
+++ b/gem/s-camino.gmi
@@ -0,0 +1,33 @@
+# s-camino... el camino del ensamblador (?)
+
+veo razones varias, múltiples, para el estudio poético y contemplativo de la computación a bajo nivel.
+
+específicamente aquí me refiero al programar en el llamado lenguaje ensamblador (¿o idioma ensamblador?)
+
+en otros contextos se puede hablar de que conviene hacerlo buscando eficiencia, velocidad, haciendo el sacrificio de descender por las escaleras para mover los fierros; ensuciarse las manos mientras se observa la complejidad del dispositivo... pero todo sea por la productividad y el resultado óptimo que se encontrará a final del tunel.
+
+aquí no estamos en ese contexto, claramente. pero justo esa impracticidad, esa mugre, esa manualidad o artesanalidad, la imagen de que a fin de cuentas (solo) estamos moviendo bits de aquí para allá (conectados de tal manera que algo más sucede) es la que llama la atención.
+
+¿qué tal si acompañamos a la máquina en un nivel cercano al que será su propósito (¿o condena?) de vida?
+
+tomamos conciencia de cada uno de los pasos por la que la haremos pasar sin otra opción más que seguir, seguir, seguir…
+
+y sí, al escribir y programar en ensamblador vamos con lentitud, porque las convenciones son extrañas (todo un dialecto que tal vez busca alejar a quien no tiene cierto perfil), porque es un mundo que contrasta con la costumbre de la eficiencia, de los resultados inmediatos.
+
+además, ¿cuál es la prisa, por qué querer hacer tanto?
+
+hacer un programa se puede convertir en un ritual; la invocación del libro de instrucciones y conexiones, la planeación y reflexión antes de escribir la primera letra; tardarse horas en algo que aquellas estructuras de facilidad, practicidad, te permiten hacer en minutos, segundos (¿pero te quitan toda la magia, todo el asombro y confrontación con lo que realmente está pasando?)
+
+la no portabilidad del código está a nuestro favor, porque implica rehacerlo cada vez (o cuando sea necesario), re-contemplar, ir lento. de nuevo, ¿cuál es la prisa?
+
+estoy de acuerdo, es un mundo inaccesible (¿similar a cualquier otro tipo de hechicería?), pero parte de la labor que me autoasigno es hacerle puertas (o grietas, hoyos, y adentro madrigueras) para poderlo compartir.
+
+no cualquiera tiene el tiempo... igual aquí andaremos, con paciencia, y un paso a la vez.
+
+(escrito el 12019-07-05)
+
+enlazan aquí:
+=> ./avr-asm.gmi {avr-asm}
+=> ./darena.gmi {darena}
+
+página actualizada en: sejmana-1660, día 1 (12021-05-20)
diff --git a/gem2gem.awk b/gem2gem.awk
index e854d7e..eea63f6 100644
--- a/gem2gem.awk
+++ b/gem2gem.awk
@@ -32,6 +32,6 @@
END{
print ""
- print "página actualizada en: " fechasjm
+ print "página actualizada en: " fechasjm " (1" fecha ")"
# fecha = system( "date -r " FILENAME " --rfc-3339=date" )
}
diff --git a/gemtext2html.awk b/gemtext2html.awk
index ab4d44e..c1b44a7 100644
--- a/gemtext2html.awk
+++ b/gemtext2html.awk
@@ -321,6 +321,7 @@ END{
print "<p><a href='./index.html'>{" sitio "}</a></p>"
print "<p>página actualizada en: "
print "<time datetime='"fecha"'>" fechasjm "</time>"
+ print " (1"fecha")"
print "</p>"
# fecha = system( "date -r " FILENAME " --rfc-3339=date" )
# print "</p>"
Un proyecto texto-plano.xyz