💾 Archived View for compudanzas.net › tomatimer.gmi captured on 2023-11-04 at 11:24:33. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2023-03-20)
-=-=-=-=-=-=-
a small pomodoro timer on an attiny85, programmed with avr-asm.
part of the s-camino practice.
tomatimer works as a 25 and 5 minutes timer, cycling between them.
a couple of LEDs indicate via blinking which one of the two timers is active at a given moment.
at the end of each timer, a buzzer plays an alarm during some seconds.
all the durations can be reconfigured via the source code if needed.
┌──────┐ │1 8│ VCC │2 7│ PB2: LED state 1 │3 6│ PB1: LED state 0 GND │4 5│ PB0: Buzzer └──────┘
LEDs are connected such that an output of "high" will turn them on.
with billingual comments
; tomatimer.S #include <avr/io.h> ; TIMER1 tiene su reloj a clk/512 (~1953 Hz) ; contando 244 pulsos se va a 8Hz (frame freq) ; i.e. 8 frames son 1 segundo ; r16 y r17 se usan como registros auxiliares ; duraciones en minutos de los timers #define DUR_TIMER0 25 #define DUR_TIMER1 5 ; duraciones en segundos de la alarma #define DUR_ALARMA0 3 #define DUR_ALARMA1 5 ; más chico es más agudo #define WAVE_PERIOD0 3 #define WAVE_PERIOD1 6 ; teórico: 244 #define TIMER1_PERIOD 240 #define rFrames r20 #define rSegundos r21 #define rMinutos r22 #define rFlags r23 #define fAlarmOn 0 #define fAlarmLevel 1 #define fCualTimer 2 #define pinAlarm PB0 #define pinState0 PB1 #define pinState1 PB2 ; para hacer fast modulo 8 #define MASK_FRAMES 0x07 ; *********************** ; vectores de interrupts: ; *********************** ; Reset .org 0x0000 rjmp main ; dirección 0x0003 * 2 .org 0x0006 rjmp timer1compareA_isr ; dirección 0x0009 * 2 .org 0x0012 rjmp timer1compareB_isr ; *********************** ; Main ; *********************** .org 0x001E main: ;---------------------------------- ; configuración general ;---------------------------------- ; habilita interrupciones sei ; pin PB0 como pin de salida ldi r16, (1<<DDB2) | (1<<DDB1) | (1<<DDB0) ; pins de salida sts DDRB, r16 ;---------------------------------- ; configuración TIMER0 para buzzer ;--------------------------------- ; CS0: 0b011, clock select clk/64 ; WGM0: 0b010, Clear timer on compare match (CTC mode) ; COM0A: 0b01, toggle OCOA on compare match (0b00 para apagar) ldi r16, (0<<WGM02) | (0<<CS02) | (1<<CS01) | (1<<CS00) sts TCCR0B, r16 ldi r16, (0<<COM0A1) | (1<<COM0A0) | (1<<WGM01) | (0<<WGM00) sts TCCR0A, r16 ; el TOP es el valor en OCR0A ; más pequeño es más agudo ldi r16, WAVE_PERIOD0 sts OCR0A, r16 ;---------------------------------- ; configuración TIMER1 para frames ;---------------------------------- ; CS1 en 0b1010 es CK/512 ldi r16, (1<<CTC1) | (1<<CS13) | (0<<CS12) | (1<<CS11) | (0<<CS10) sts TCCR1, r16 ; establece el valor A al que cuenta el timer1 para interrupt ldi r16, TIMER1_PERIOD sts OCR1A, r16 ; establece el valor C al que cuenta el timer1 para resetear sts OCR1C, r16 ; establece el valor B para mitad de periodo lsr r16 ; divide entre 2 sts OCR1B, r16 ; set timer output compare A interrupt enable 1 ; y timer output compare B interrupt enable ldi r16, (1<<OCIE1A) | (1<<OCIE1B) sts TIMSK, r16 ;enciende alarma ldi rFlags, (1<<fAlarmOn) ; time count ldi rFrames, 0 ; frames ldi rSegundos, 0 ; seconds ldi rMinutos, 0 ; minutes ; enciede state 0 ldi r16, (1<<pinState0) sts PORTB, r16 loop: sleep rjmp loop ; ----------------------- ; interrupts ; main time counting timer1compareA_isr: ; apaga alarm level clt bld rFlags, fAlarmLevel ; apaga pwm output lds r16, TCCR0A andi r16, ~(1<<COM0A0) sts TCCR0A, r16 ; incrementa frames inc rFrames andi rFrames, MASK_FRAMES breq incrementsec ; salta si rFrames%8 == 0 reti incrementsec: inc rSegundos ; cuenta segundos lds r16, PORTB ; en qué timer estamos? bst rFlags, fCualTimer brts checksegundos1 ; salta si es el 1 checksegundos0: bst rSegundos, 0 brts ledstate0off ledstate0on: ori r16, (1<<pinState0) rjmp comparesegundos0 ledstate0off: andi r16, ~(1<<pinState0) comparesegundos0: sts PORTB, r16 cpi rSegundos, DUR_ALARMA0 ; time == DUR_ALARMA0? brne updateminutes rjmp turnalarmoff checksegundos1: bst rSegundos,0 brts ledstate1off ledstate1on: ori r16, (1<<pinState1) rjmp comparesegundos1 ledstate1off: andi r16, ~(1<<pinState1) comparesegundos1: sts PORTB, r16 cpi rSegundos, DUR_ALARMA1 ; time == DUR_ALARMA0? brne updateminutes turnalarmoff: ; si es la duración correspondiente, apaga alarma clt bld rFlags, fAlarmOn updateminutes: cpi rSegundos,60 ; segundos == 60? breq minute reti minute: ldi rSegundos, 0 ; reset seconds inc rMinutos ; increment minutes bst rFlags, fCualTimer brts checkminutes1 checkminutes0: cpi rMinutos, DUR_TIMER0 breq firealarm reti checkminutes1: cpi rMinutos, DUR_TIMER1 breq firealarm reti firealarm: ldi rMinutos, 0 ; reset minutes ; inicia alarma set bld rFlags, fAlarmOn ; invierte timer bst rFlags, fCualTimer brts settimer0 ; salta si el timer es 1 settimer1: set bld rFlags,fCualTimer ; cambia tono de alarma ldi r16, WAVE_PERIOD1 sts OCR0A, r16 ; apaga otro led lds r16, PORTB andi r16, ~(1<<pinState0) sts PORTB, r16 reti settimer0: clt bld rFlags,fCualTimer ; cambia tono de alarma ldi r16, WAVE_PERIOD0 sts OCR0A, r16 ; apaga otro led lds r16, PORTB andi r16, ~(1<<pinState1) sts PORTB, r16 reti ; enciende pin de alarma timer1compareB_isr: bst rFlags, fAlarmOn ; bit store ; branch if T bit is set brts turnonalarmlevel reti turnonalarmlevel: ; set alarmlevel on set bld rFlags, fAlarmLevel ; enciende pwm output lds r16, TCCR0A ori r16, (1<<COM0A0) sts TCCR0A, r16 reti
to assemble:
make hex
to flash:
make flash
# Makefile # nombre del programa sin .S : PROG = tomatimer # config hardware BOARD = attiny85 PROGRAMMER = usbasp # ensambla programa .S 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)
text, images, and code are shared with the peer production license