AvrAsmLib/src/avr_asm_lib/avr_asm_lib.S

134 lines
2.9 KiB
ArmAsm
Raw Normal View History

2021-01-22 02:24:05 +03:00
; Copyright 2021 KoroLion (https://github.com/KoroLion)
2021-01-19 12:28:33 +03:00
#define __SFR_OFFSET 0
#define LED_PORT 7
#include "avr/io.h" // ~ #include "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 DDRD, LED_PORT
2021-01-22 02:24:05 +03:00
ret
led_enable:
sbi PORTD, LED_PORT
ret
2021-01-19 12:28:33 +03:00
2021-01-22 02:24:05 +03:00
led_disable:
cbi PORTD, LED_PORT
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 \port, 0
2021-01-21 18:27:54 +03:00
breq end_convert ; = 0 => no need to convert (already set mask to port 0)
2021-01-22 02:24:05 +03:00
mov r30, \port
2021-01-21 18:27:54 +03:00
convert:
lsl r31 ; logic shift left ~ r31 * 2
dec r30
cpi r30, 0
brne convert
end_convert:
com r31 ; inverting mask (00001000 -> 11110111)
; setting correct DDRC using mask
in r30, DDRC
and r30, r31 ; applying mask (11111111 and 11110111 = 11110111)
out DDRC, 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, res_high, res_low
2021-01-19 12:28:33 +03:00
ldi r30, 0b00000000
sts PRR, 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, 0b11000000
2021-01-22 02:24:05 +03:00
or r30, \port
2021-01-19 12:28:33 +03:00
sts ADMUX, 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, 0b11000111
sts ADCSRA, r30
wait_adc:
lds r30, ADCSRA
ldi r31, 0b01000000
and r31, r30
cpi r31, 0
brne wait_adc
2021-01-22 02:24:05 +03:00
lds \res_low, ADCL
lds \res_high, ADCH
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, 0b00000011
2021-01-22 02:24:05 +03:00
and \res_high, r31
.endm
2021-01-19 12:28:33 +03:00
2021-01-22 02:24:05 +03:00
.macro divw10 divident_high, divident_low
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 \divident_low, 10
2021-01-21 18:27:54 +03:00
brlo division_low_end ; <
continue_division:
2021-01-22 02:24:05 +03:00
sbiw \divident_low, 10
2021-01-21 18:27:54 +03:00
inc r30
rjmp division
division_low_end:
2021-01-22 02:24:05 +03:00
cpi \divident_high, 0
2021-01-21 18:27:54 +03:00
brne continue_division
2021-01-22 02:24:05 +03:00
cpi \divident_low, 5
2021-01-21 18:27:54 +03:00
brlo not_inc ; <
inc r30
not_inc:
2021-01-22 02:24:05 +03:00
.endm
lm35_init:
; r25:r24 is the first arg
subi r24, 14 ; because A0 is D14
pin_mode_input r24
sts lm35_port, 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, lm35_port
adc_read r24, r25, r24
divw10 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