2021-01-22 02:24:05 +03:00
; Copyright 2021 KoroLion (https://github.com/KoroLion)
2021-01-19 12:28:33 +03:00
# define _ _ S F R _ O F F S E T 0
# define L E D _ P O R T 7
# include " a v r / i o . h " / / ~ #i n c l u d e " avr/iom328p.h "
2021-01-21 18:27:54 +03:00
.section .bss
lm35_port : .byte 0
.section .text
.global lm35_init
.global lm35_read
2021-01-22 02:24:05 +03:00
.global led_init
.global led_enable
.global led_disable
led_init :
2021-01-19 12:28:33 +03:00
sbi D D R D , L E D _ P O R T
2021-01-22 02:24:05 +03:00
ret
led_enable :
sbi P O R T D , L E D _ P O R T
ret
2021-01-19 12:28:33 +03:00
2021-01-22 02:24:05 +03:00
led_disable :
cbi P O R T D , L E D _ P O R T
2021-01-19 12:28:33 +03:00
ret
2021-01-21 18:27:54 +03:00
2021-01-22 02:24:05 +03:00
.macro pin_mode_input port
; sets analog port as input
2021-01-21 18:27:54 +03:00
ldi r31 , 1 ; means port 0
2021-01-22 02:24:05 +03:00
cpi \ p o r t , 0
2021-01-21 18:27:54 +03:00
breq e n d _ c o n v e r t ; = 0 => no need to convert (already set mask to port 0)
2021-01-22 02:24:05 +03:00
mov r30 , \ p o r t
2021-01-21 18:27:54 +03:00
convert :
lsl r31 ; logic shift left ~ r31 * 2
dec r30
cpi r30 , 0
brne c o n v e r t
end_convert :
com r31 ; inverting mask (00001000 -> 11110111)
; setting correct DDRC using mask
in r30 , D D R C
and r30 , r31 ; applying mask (11111111 and 11110111 = 11110111)
out D D R C , r30
2021-01-22 02:24:05 +03:00
.endm
2021-01-21 18:27:54 +03:00
2021-01-22 02:24:05 +03:00
.macro adc_read port, r e s _ h i g h , r e s _ l o w
2021-01-19 12:28:33 +03:00
ldi r30 , 0 b00 0 0 0 0 0 0
sts P R R , r30
2021-01-22 02:24:05 +03:00
2021-01-19 12:28:33 +03:00
; first two bits are for the ref voltage
2021-01-21 18:27:54 +03:00
; 11 means using internal 1.1v atmega voltage for adc
2021-01-19 12:28:33 +03:00
; last three bits are for the analog port number
ldi r30 , 0 b11 0 0 0 0 0 0
2021-01-22 02:24:05 +03:00
or r30 , \ p o r t
2021-01-19 12:28:33 +03:00
sts A D M U X , r30
2021-01-22 02:24:05 +03:00
; last 3 bits (111 means 128)
; ADC Prescaler Select Bits (ADPS): ADPS2, ADPS1 and ADPS0 bits are used to set circuit clock frequency.
; For ADC circuitry to work at its maximum resolution needs to be supplied with 50 kHz to 200 kHz frequency as per the datasheet;
; but the system clock will be generally higher (8 MHz, 10 MHz, 16 MHz etc).
; To reduce it to required frequency we use ADC prescaler bits. Suppose we have system clock with frequency 10Mhz (10000000 Hz) and set division factor to 64,
; then ADC clock frequency is 10000000/64 = 156250Hz = 156.25 KHz, which is between 50 to 200 KHz as mentioned in the datasheet.
; (http://www.robotplatform.com/knowledge/ADC/adc_tutorial_2.html)
;
; 16 MHz / 128 = 16000000 Hz / 128 = 125000 Hz = 125 KHz => OK!
2021-01-19 12:28:33 +03:00
ldi r30 , 0 b11 0 0 0 1 1 1
sts A D C S R A , r30
wait_adc :
lds r30 , A D C S R A
ldi r31 , 0 b01 0 0 0 0 0 0
and r31 , r30
cpi r31 , 0
brne w a i t _ a d c
2021-01-22 02:24:05 +03:00
lds \ r e s _ l o w , A D C L
lds \ r e s _ h i g h , A D C H
2021-01-21 18:27:54 +03:00
; clearing unused bits to be sure they're zero
2021-01-19 12:28:33 +03:00
ldi r31 , 0 b00 0 0 0 0 1 1
2021-01-22 02:24:05 +03:00
and \ r e s _ h i g h , r31
.endm
2021-01-19 12:28:33 +03:00
2021-01-22 02:24:05 +03:00
.macro divw10 divident_ h i g h , d i v i d e n t _ l o w
2021-01-21 18:27:54 +03:00
; r30 - res
2021-01-22 02:24:05 +03:00
; divident_low - quotient
2021-01-21 18:27:54 +03:00
ldi r30 , 0
division :
2021-01-22 02:24:05 +03:00
cpi \ d i v i d e n t _ l o w , 1 0
2021-01-21 18:27:54 +03:00
brlo d i v i s i o n _ l o w _ e n d ; <
continue_division :
2021-01-22 02:24:05 +03:00
sbiw \ d i v i d e n t _ l o w , 1 0
2021-01-21 18:27:54 +03:00
inc r30
rjmp d i v i s i o n
division_low_end :
2021-01-22 02:24:05 +03:00
cpi \ d i v i d e n t _ h i g h , 0
2021-01-21 18:27:54 +03:00
brne c o n t i n u e _ d i v i s i o n
2021-01-22 02:24:05 +03:00
cpi \ d i v i d e n t _ l o w , 5
2021-01-21 18:27:54 +03:00
brlo n o t _ i n c ; <
inc r30
not_inc :
2021-01-22 02:24:05 +03:00
.endm
lm35_init :
; r25:r24 is the first arg
subi r24 , 1 4 ; because A0 is D14
pin_ m o d e _ i n p u t r24
sts l m 3 5 _ p o r t , r24
ret
lm35_read :
cli ; forbids interruptions
2021-01-21 18:27:54 +03:00
2021-01-22 02:24:05 +03:00
lds r24 , l m 3 5 _ p o r t
adc_ r e a d r24 , r25 , r24
divw1 0 r25 , r24
2021-01-21 18:27:54 +03:00
mov r24 , r30 ; uint8_t return value
adiw r24 , 2 ; due to LM35 formula (2C to 150C)
2021-01-19 12:28:33 +03:00
sei ; allow interruptions
clr r1 ; c requirement
ret