Skip to content

Instantly share code, notes, and snippets.

@melvinsh
Created April 17, 2020 12:00
Show Gist options
  • Save melvinsh/0143a520798738cf87948cc305a74ba0 to your computer and use it in GitHub Desktop.
Save melvinsh/0143a520798738cf87948cc305a74ba0 to your computer and use it in GitHub Desktop.
Alarm Clock
.include "m32def.inc"
;===============================;
; Define all constants (.equ) ;
;===============================;
.equ digit0 = 0b11110111
.equ digit1 = 0b10100100
.equ digit2 = 0b11011101
.equ digit3 = 0b11101101
.equ digit4 = 0b10101110
.equ digit5 = 0b11101011
.equ digit6 = 0b11111011
.equ digit7 = 0b10100101
.equ digit8 = 0b01111111
.equ digit9 = 0b11101111
;========================;
; Define all registers ;
;========================;
.def tmp = r16 ; general use temp register
.def tmpdigit = r17 ; temp register for digits
.def counter = r24 ; counter for time
.def buzz = r25 ; buzz = alarm on or off
.def alarm_digit1 = r26
.def alarm_digit2 = r27
.def alarm_digit3 = r28
.def alarm_digit4 = r29
.def alarm_digit5 = r30
.def alarm_digit6 = r31
.def time_digit1 = r18
.def time_digit2 = r19
.def time_digit3 = r20
.def time_digit4 = r21
.def time_digit5 = r22
.def time_digit6 = r23
.org 0x0000
rjmp init
.org OC1Aaddr
rjmp TIMER_COUNTER_INC
;==================;
; Initialisation ;
;==================;
init:
;=========================;
; Set the stack pointer ;
;=========================;
STACK_Init:
ldi tmp, HIGH(RAMEND)
out SPH, tmp
ldi tmp, LOW(RAMEND)
out SPL, tmp
;=============================;
; Init the RS232 connection ;
;=============================;
RS232_Init:
clr tmp
out UBRRH, tmp
ldi tmp, 35
out UBRRL, tmp
ldi tmp, (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0)
out UCSRC, tmp
ldi tmp, (1 << RXEN) | (1 << TXEN)
out UCSRB, tmp
;============================;
; Init the interrupt timer ;
;============================;
INT_Init:
ldi tmp, high(4320) ; write 43200 to OCR1 (this equals 1 second)
out OCR1AH, tmp
ldi tmp, low(4320) ; write 43200 to OCR1 (this equals 1 second)
out OCR1AL, tmp
ldi tmp, (1 << CS12) | (1 << WGM12)
out TCCR1B, tmp
ldi tmp, (1 << OCIE1A) ; enable interrupt
out TIMSK, tmp
sei ; all interrupts
;====================================;
; Set the time on start (00:01:00) ;
;====================================;
ldi time_digit1, 0
ldi time_digit2, 0
ldi time_digit3, 0
ldi time_digit4, 1
ldi time_digit5, 0
ldi time_digit6, 0
;==========================================;
; Set the alarm time on start (00:02:00) ;
;==========================================;
ldi alarm_digit1, 0
ldi alarm_digit2, 0
ldi alarm_digit3, 0
ldi alarm_digit4, 2
ldi alarm_digit5, 0
ldi alarm_digit6, 0
;========================================;
; Subroutines to blink all time digits ;
;========================================;
blink_all:
cpi counter, 10 ; counter == 10?
brne blink_all2 ; not equal -> branch to blink_all2
clr counter
rcall time_inc
rcall send_time_alarm_off
in tmp, PINA ; port a (switches) to temp
cpi tmp, 0xfd ; sw1 pressed?
breq blink_hours ; true -> branch to blink_hours
blink_all2:
cpi counter, 5 ; counter == 5?
brne blink_all3 ; not equal -> branch to blink_all3
rcall send_blink
blink_all3:
rjmp blink_all ; go back to blink_all
; everything below is basically the same but with hours, minutes and seconds.
blink_hours:
cpi counter, 10
brne blink_hours2
clr counter
rcall send_time_alarm_off
in tmp, PINA
cpi tmp, 0xfd
breq blink_mins
in tmp, PINA
cpi tmp, 0xfe
brne blink_hours2
rcall inc_hrs
blink_hours2:
cpi counter, 5
brne blink_hours3
rcall send_blink_12
blink_hours3:
rjmp blink_hours
blink_mins:
cpi counter, 10
brne blink_mins2
clr counter
rcall send_time_alarm_off
in tmp, PINA
cpi tmp, 0xfd
breq blink_secs
in tmp, PINA
cpi tmp, 0xfe
brne blink_mins2
rcall inc_mins
blink_mins2:
cpi counter, 5
brne blink_mins3
rcall send_blink_34
blink_mins3:
rjmp blink_mins
blink_secs:
cpi counter, 10
brne blink_secs2
clr counter
rcall send_time_alarm_off
in tmp, PINA
cpi tmp, 0xfd
breq alarm_hours
in tmp, PINA
cpi tmp, 0xfe
brne blink_secs2
rcall inc_secs
blink_secs2:
cpi counter, 5
brne blink_secs3
rcall send_blink_56
blink_secs3:
rjmp blink_secs
;=========================================;
; Subroutines to blink all alarm digits ;
;=========================================;
alarm_hours:
cpi counter, 10
brne alarm_hours2
clr counter
rcall time_inc
rcall send_alarm
in tmp, PINA
cpi tmp, 0xfd
breq alarm_mins
in tmp, PINA
cpi tmp, 0xfe
brne alarm_hours2
rcall inc_alarm_hrs
alarm_hours2:
cpi counter, 5
brne alarm_hours3
rcall send_alarm_blink_12
alarm_hours3:
rjmp alarm_hours
alarm_mins:
cpi counter, 10
brne alarm_mins2
clr counter
rcall time_inc
rcall send_alarm
in tmp, PINA
cpi tmp, 0xfd
breq alarm_secs
in tmp, PINA
cpi tmp, 0xfe
brne alarm_mins2
rcall inc_alarm_mins
alarm_mins2:
cpi counter, 5
brne alarm_mins3
rcall send_alarm_blink_34
alarm_mins3:
rjmp alarm_mins
alarm_secs:
cpi counter, 10
brne alarm_secs2
clr counter
rcall time_inc
rcall send_alarm
in tmp, PINA
cpi tmp, 0xfd
breq alarm_text
in tmp, PINA
cpi tmp, 0xfe
brne alarm_secs2
rcall inc_alarm_secs
alarm_secs2:
cpi counter, 5
brne alarm_secs3
rcall send_alarm_blink_56
alarm_secs3:
rjmp alarm_secs
;=======================================;
; Subroutines to blink the alarm text ;
;=======================================;
alarm_text:
cpi counter, 10
brne alarm_text2
clr counter
rcall time_inc
rcall send_alarm
in tmp, PINA
cpi tmp, 0xfd
breq normal_time_alarm_on
in tmp, PINA
cpi tmp, 0xfe
brne alarm_text2
rjmp alarm_text_off
alarm_text2:
cpi counter, 5
brne alarm_text3
rcall send_alarmtext_off
alarm_text3:
rjmp alarm_text
alarm_text_off:
cpi counter, 10
brne alarm_text_off3
clr counter
rcall time_inc
rcall send_alarmtext_off
in tmp, PINA
cpi tmp, 0xfd
breq alarm_text_off2
in tmp, PINA
cpi tmp, 0xfe
brne alarm_text_off3
rjmp alarm_text_on
alarm_text_off2:
rjmp normal_time_alarm_off
alarm_text_off3:
rjmp alarm_text_off
alarm_text_on:
cpi counter, 10
brne alarm_text_on3
clr counter
rcall time_inc
rcall send_alarm
in tmp, PINA
cpi tmp, 0xfd
breq alarm_text_on2
in tmp, PINA
cpi tmp, 0xfe
brne alarm_text_on3
rjmp alarm_text_off
alarm_text_on2:
rjmp normal_time_alarm_on
alarm_text_on3:
rjmp alarm_text_on
;==================================;
; Show the time (alarm text off) ;
;==================================;
normal_time_alarm_off:
cpi counter, 10
brne normal_time_alarm_off2
clr counter
rcall time_inc
rcall send_time_alarm_off
in tmp, PINA
cpi tmp, 0xfd
brne normal_time_alarm_off2
rjmp blink_hours
normal_time_alarm_off2:
rjmp normal_time_alarm_off
;=================================;
; Show the time (alarm text on) ;
;=================================;
normal_time_alarm_on:
cpi counter, 10
brne normal_time_alarm_on2
clr counter
rcall time_inc
rcall alarm_check
rcall send_time_alarm_on
in tmp, PINA
cpi tmp, 0xfd
brne normal_time_alarm_on2
rjmp blink_hours
normal_time_alarm_on2:
cpi buzz, 1
breq buzzer_on
rjmp normal_time_alarm_on
;================================;
; Show the time while alarming ;
;================================;
buzzer_on:
cpi counter, 10
brne buzzer_on3
clr counter
clr tmp
out DDRB, tmp
rcall time_inc
rcall buzzer
in tmp, PINA
cpi tmp, 0xfd
brne buzzer_on3
buzzer_on2:
rjmp normal_time_alarm_off
buzzer_on3:
cpi counter, 5
brne buzzer_on4
ldi tmp, 0xff
out DDRB, tmp
buzzer_on4:
rjmp buzzer_on
;===================;
; Timer interrupt ;
;===================;
TIMER_COUNTER_INC:
inc counter
reti
;====================;
; UART Transmitter ;
;====================;
send:
in tmp, USR
sbrs tmp, UDRE
rjmp send
out UDR, tmpdigit
ret
;==============================================;
; Subroutines to convert a number to a digit ;
;==============================================;
number_to_digit:
cpi tmp, 0
breq to0
cpi tmp, 1
breq to1
cpi tmp, 2
breq to2
cpi tmp, 3
breq to3
cpi tmp, 4
breq to4
cpi tmp, 5
breq to5
cpi tmp, 6
breq to6
cpi tmp, 7
breq to7
cpi tmp, 8
breq to8
cpi tmp, 9
breq to9
ret
to0:
ldi tmpdigit, digit0
ret
to1:
ldi tmpdigit, digit1
ret
to2:
ldi tmpdigit, digit2
ret
to3:
ldi tmpdigit, digit3
ret
to4:
ldi tmpdigit, digit4
ret
to5:
ldi tmpdigit, digit5
ret
to6:
ldi tmpdigit, digit6
ret
to7:
ldi tmpdigit, digit7
ret
to8:
ldi tmpdigit, digit8
ret
to9:
ldi tmpdigit, digit9
ret
;=====================================;
; Subroutines to increment the time ;
;=====================================;
time_inc:
inc time_digit6
cpi time_digit6, 10
breq timer1
ret
timer1:
clr time_digit6
inc time_digit5
cpi time_digit5, 6
breq timer2
ret
timer2:
clr time_digit5
inc time_digit4
cpi time_digit4, 10
breq timer3
ret
timer3:
clr time_digit4
inc time_digit3
cpi time_digit3, 6
breq timer4
ret
timer4:
clr time_digit3
inc time_digit2
cpi time_digit2, 4
breq timer5
cpi time_digit2, 10
breq timer6
ret
timer6:
clr time_digit2
inc time_digit1
ret
timer5:
cpi time_digit1, 2
breq timerreset
ret
timerreset:
clr time_digit2
clr time_digit1
ret
;======================================;
; Subroutines to send the time ;
; These subroutines are out of reach ;
; When put at around line 400 ;
;======================================;
send_time_alarm_off:
mov tmp, time_digit1
rcall number_to_digit
rcall send
mov tmp, time_digit2
rcall number_to_digit
rcall send
mov tmp, time_digit3
rcall number_to_digit
rcall send
mov tmp, time_digit4
rcall number_to_digit
rcall send
mov tmp, time_digit5
rcall number_to_digit
rcall send
mov tmp, time_digit6
rcall number_to_digit
rcall send
ldi tmpdigit, 0b00000110
rcall send
ret
send_time_alarm_on:
mov tmp, time_digit1
rcall number_to_digit
rcall send
mov tmp, time_digit2
rcall number_to_digit
rcall send
mov tmp, time_digit3
rcall number_to_digit
rcall send
mov tmp, time_digit4
rcall number_to_digit
rcall send
mov tmp, time_digit5
rcall number_to_digit
rcall send
mov tmp, time_digit6
rcall number_to_digit
rcall send
ldi tmpdigit, 0b00000111
rcall send
ret
send_blink:
ldi tmpdigit, 0b00000000
rcall send
ldi tmpdigit, 0b00000000
rcall send
ldi tmpdigit, 0b00000000
rcall send
ldi tmpdigit, 0b00000000
rcall send
ldi tmpdigit, 0b00000000
rcall send
ldi tmpdigit, 0b00000000
rcall send
ldi tmpdigit, 0b00000110
rcall send
ret
send_blink_12:
ldi tmpdigit, 0b00000000
rcall send
ldi tmpdigit, 0b00000000
rcall send
mov tmp, time_digit3
rcall number_to_digit
rcall send
mov tmp, time_digit4
rcall number_to_digit
rcall send
mov tmp, time_digit5
rcall number_to_digit
rcall send
mov tmp, time_digit6
rcall number_to_digit
rcall send
ldi tmpdigit, 0b00000110
rcall send
ret
send_blink_34:
mov tmp, time_digit1
rcall number_to_digit
rcall send
mov tmp, time_digit2
rcall number_to_digit
rcall send
ldi tmpdigit, 0b00000000
rcall send
ldi tmpdigit, 0b00000000
rcall send
mov tmp, time_digit5
rcall number_to_digit
rcall send
mov tmp, time_digit6
rcall number_to_digit
rcall send
ldi tmpdigit, 0b00000110
rcall send
ret
send_blink_56:
mov tmp, time_digit1
rcall number_to_digit
rcall send
mov tmp, time_digit2
rcall number_to_digit
rcall send
mov tmp, time_digit3
rcall number_to_digit
rcall send
mov tmp, time_digit4
rcall number_to_digit
rcall send
ldi tmpdigit, 0b00000000
rcall send
ldi tmpdigit, 0b00000000
rcall send
ldi tmpdigit, 0b00000110
rcall send
ret
;================================================;
; Increment hours, minutes and seconds of time ;
;================================================;
inc_hrs:
inc time_digit2
cpi time_digit2, 4
breq inc_hrs1
cpi time_digit2, 10
breq inc_hrs2
ret
inc_hrs2:
clr time_digit2
inc time_digit1
ret
inc_hrs1:
cpi time_digit1, 2
breq inc_hrs_reset
ret
inc_hrs_reset:
clr time_digit2
clr time_digit1
ret
inc_mins:
inc time_digit4
cpi time_digit4, 10
breq inc_mins1
ret
inc_mins1:
clr time_digit4
inc time_digit3
cpi time_digit3, 6
breq inc_mins2
ret
inc_mins2:
clr time_digit3
ret
inc_secs:
inc time_digit6
cpi time_digit6, 10
breq inc_secs1
ret
inc_secs1:
clr time_digit6
inc time_digit5
cpi time_digit5, 6
breq inc_secs2
ret
inc_secs2:
clr time_digit5
;==================================;
; Subroutines to send ALARM time ;
;==================================;
send_alarm:
mov tmp, alarm_digit1
rcall number_to_digit
rcall send
mov tmp, alarm_digit2
rcall number_to_digit
rcall send
mov tmp, alarm_digit3
rcall number_to_digit
rcall send
mov tmp, alarm_digit4
rcall number_to_digit
rcall send
mov tmp, alarm_digit5
rcall number_to_digit
rcall send
mov tmp, alarm_digit6
rcall number_to_digit
rcall send
ldi tmpdigit, 0b00000111
rcall send
ret
send_alarmtext_off:
mov tmp, alarm_digit1
rcall number_to_digit
rcall send
mov tmp, alarm_digit2
rcall number_to_digit
rcall send
mov tmp, alarm_digit3
rcall number_to_digit
rcall send
mov tmp, alarm_digit4
rcall number_to_digit
rcall send
mov tmp, alarm_digit5
rcall number_to_digit
rcall send
mov tmp, alarm_digit6
rcall number_to_digit
rcall send
ldi tmpdigit, 0b00000110
rcall send
ret
;=================================================;
; Increment hours, minutes and seconds of ALARM ;
;=================================================;
inc_alarm_hrs:
inc alarm_digit2
cpi alarm_digit2, 4
breq inc_alarm_hrs1
cpi alarm_digit2, 10
breq inc_alarm_hrs2
ret
inc_alarm_hrs1:
cpi alarm_digit1, 2
breq inc_alarm_hrs_reset
ret
inc_alarm_hrs2:
clr alarm_digit2
inc alarm_digit1
ret
inc_alarm_hrs_reset:
clr alarm_digit2
clr alarm_digit1
ret
inc_alarm_mins:
inc alarm_digit4
cpi alarm_digit4, 10
breq inc_alarm_mins1
ret
inc_alarm_mins1:
clr alarm_digit4
inc alarm_digit3
cpi alarm_digit3, 6
breq inc_alarm_mins2
ret
inc_alarm_mins2:
clr alarm_digit3
ret
inc_alarm_secs:
inc alarm_digit6
cpi alarm_digit6, 10
breq inc_alarm_secs1
ret
inc_alarm_secs1:
clr alarm_digit6
inc alarm_digit5
cpi alarm_digit5, 6
breq inc_alarm_secs2
ret
inc_alarm_secs2:
clr alarm_digit5
buzzer:
mov tmp, time_digit1
rcall number_to_digit
rcall send
mov tmp, time_digit2
rcall number_to_digit
rcall send
mov tmp, time_digit3
rcall number_to_digit
rcall send
mov tmp, time_digit4
rcall number_to_digit
rcall send
mov tmp, time_digit5
rcall number_to_digit
rcall send
mov tmp, time_digit6
rcall number_to_digit
rcall send
ldi tmpdigit, 0b00001111
rcall send
ret
;=================================================================;
; Subroutine to determine whether the alarm should be going off ;
;=================================================================;
alarm_check:
cp time_digit1, alarm_digit1
breq alarm_check1
ret
alarm_check1:
cp time_digit2, alarm_digit2
breq alarm_check2
ret
alarm_check2:
cp time_digit3, alarm_digit3
breq alarm_check3
ret
alarm_check3:
cp time_digit4, alarm_digit4
breq alarm_check4
ret
alarm_check4:
cp time_digit5, alarm_digit5
breq alarm_check5
ret
alarm_check5:
cp time_digit6, alarm_digit6
breq alarm_check6
ret
alarm_check6:
ldi buzz, 1
ret
;================================================================;
; Subroutines to send the alarm while some digits are blinking ;
;================================================================;
send_alarm_blink_12:
ldi tmpdigit, 0b00000000
rcall send
ldi tmpdigit, 0b00000000
rcall send
mov tmp, alarm_digit3
rcall number_to_digit
rcall send
mov tmp, alarm_digit4
rcall number_to_digit
rcall send
mov tmp, alarm_digit5
rcall number_to_digit
rcall send
mov tmp, alarm_digit6
rcall number_to_digit
rcall send
ldi tmpdigit, 0b00000110
rcall send
ret
send_alarm_blink_34:
mov tmp, alarm_digit1
rcall number_to_digit
rcall send
mov tmp, alarm_digit2
rcall number_to_digit
rcall send
ldi tmpdigit, 0b00000000
rcall send
ldi tmpdigit, 0b00000000
rcall send
mov tmp, alarm_digit5
rcall number_to_digit
rcall send
mov tmp, alarm_digit6
rcall number_to_digit
rcall send
ldi tmpdigit, 0b00000110
rcall send
ret
send_alarm_blink_56:
mov tmp, alarm_digit1
rcall number_to_digit
rcall send
mov tmp, alarm_digit2
rcall number_to_digit
rcall send
mov tmp, alarm_digit3
rcall number_to_digit
rcall send
mov tmp, alarm_digit4
rcall number_to_digit
rcall send
ldi tmpdigit, 0b00000000
rcall send
ldi tmpdigit, 0b00000000
rcall send
ldi tmpdigit, 0b00000110
rcall send
ret
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment