tomatimer
This commit is contained in:
parent
a4551e0286
commit
870701f742
Binary file not shown.
After Width: | Height: | Size: 36 KiB |
|
@ -1,3 +1,4 @@
|
|||
2021-12-17T14:00:00-06:00 built the tomatimer, a pomodoro timer on an attiny85 programmed with avr-asm {tomatimer}
|
||||
2021-12-03T16:00:00-06:00 qiudanz technique in the slomoco fall gathering {qiudanz devlog}
|
||||
2021-12-01T00:30:00-06:00 started advent of code 2021 using awk {advent of code 2021}
|
||||
2021-11-26T16:00:00-06:00 fourth qiudanz technique mini workshop {qiudanz devlog}
|
||||
|
|
|
@ -17,6 +17,11 @@ writing code closer to the machine(s)
|
|||
=> ./nibble_dice_tracker.gmi {nibble dice tracker}
|
||||
=> ./darena.gmi {darena}
|
||||
|
||||
## avr-asm
|
||||
|
||||
=> ./tomatimer.gmi {tomatimer}
|
||||
=> ./avr-asm.gmi {avr-asm}
|
||||
|
||||
## mu
|
||||
=> ./mu.gmi {mu}
|
||||
|
||||
|
@ -24,8 +29,7 @@ writing code closer to the machine(s)
|
|||
|
||||
=> ./forth.gmi {forth}
|
||||
|
||||
## others
|
||||
=> ./avr-asm.gmi {avr-asm}
|
||||
|
||||
|
||||
# command-line interface notes
|
||||
|
||||
|
|
|
@ -0,0 +1,347 @@
|
|||
# tomatimer
|
||||
|
||||
a small pomodoro timer on an attiny85, programmed with {avr-asm}.
|
||||
|
||||
part of the {s-camino} practice.
|
||||
|
||||
=> ./img/foto_tomatimer.png photo of the tomatimer: a small circuit with two leds, a buzzer, the attiny85, all of them over a plastic card.
|
||||
|
||||
# about
|
||||
|
||||
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.
|
||||
|
||||
# connections
|
||||
|
||||
```diagrama de pines
|
||||
┌──────┐
|
||||
│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.
|
||||
|
||||
# source code
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
# makefile
|
||||
|
||||
to assemble:
|
||||
|
||||
```
|
||||
make hex
|
||||
```
|
||||
|
||||
to flash:
|
||||
|
||||
```
|
||||
make flash
|
||||
```
|
||||
|
||||
## makefile
|
||||
|
||||
```
|
||||
# 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)
|
||||
```
|
Loading…
Reference in New Issue