Major refactoring
This commit is contained in:
parent
218e7701e1
commit
76c649475a
37
src/avr_asm_demo.s
Normal file
37
src/avr_asm_demo.s
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
.global init
|
||||||
|
.global blink
|
||||||
|
.global float_test
|
||||||
|
|
||||||
|
float_test:
|
||||||
|
ldi r25, 0b00111110
|
||||||
|
ldi r24, 0b00100000
|
||||||
|
ldi r23, 0b01000000
|
||||||
|
ldi r22, 0b00000000
|
||||||
|
clr r1
|
||||||
|
ret
|
||||||
|
|
||||||
|
blink:
|
||||||
|
ldi r20, 250
|
||||||
|
call delay_n_ms
|
||||||
|
ldi r20, 250
|
||||||
|
call delay_n_ms
|
||||||
|
|
||||||
|
sbi PORTD, LED_PORT ; high
|
||||||
|
ldi r20, 250
|
||||||
|
call delay_n_ms
|
||||||
|
cbi PORTD, LED_PORT ; low
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
delay_n_ms:
|
||||||
|
; delay for ~r20 * 1ms. r20, r30, and r31 are modified.
|
||||||
|
; 1 ms ~ 16000 cycles at 16MHz.
|
||||||
|
; The basic loop takes about 5 cycles, so we need about 3000 loops.
|
||||||
|
ldi r31, 3000 >> 8 ; high byte of the 3000
|
||||||
|
ldi r30, 3000 & 255 ; low byte of the 3000
|
||||||
|
delaylp:
|
||||||
|
sbiw r30, 1 ; sub word r30 1
|
||||||
|
brne delaylp ; jne delaylp
|
||||||
|
subi r20, 1
|
||||||
|
brne delay_n_ms
|
||||||
|
ret
|
|
@ -1,3 +1,5 @@
|
||||||
|
; Copyright 2021 KoroLion (https://github.com/KoroLion)
|
||||||
|
|
||||||
#define __SFR_OFFSET 0
|
#define __SFR_OFFSET 0
|
||||||
#define LED_PORT 7
|
#define LED_PORT 7
|
||||||
|
|
||||||
|
@ -8,28 +10,33 @@ lm35_port: .byte 0
|
||||||
|
|
||||||
.section .text
|
.section .text
|
||||||
|
|
||||||
.global init
|
|
||||||
.global blink
|
|
||||||
.global float_test
|
|
||||||
|
|
||||||
.global lm35_init
|
.global lm35_init
|
||||||
.global lm35_read
|
.global lm35_read
|
||||||
|
|
||||||
init:
|
.global led_init
|
||||||
|
.global led_enable
|
||||||
|
.global led_disable
|
||||||
|
|
||||||
|
|
||||||
|
led_init:
|
||||||
sbi DDRD, LED_PORT
|
sbi DDRD, LED_PORT
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
analog_pin_mode_input:
|
led_enable:
|
||||||
; sets analog pin as input
|
sbi PORTD, LED_PORT
|
||||||
; input: r24 - number of pin in DDRC I/O register
|
ret
|
||||||
; output: -
|
|
||||||
|
led_disable:
|
||||||
|
cbi PORTD, LED_PORT
|
||||||
|
ret
|
||||||
|
|
||||||
; r31 mask to set 0 in I/O register
|
|
||||||
|
.macro pin_mode_input port
|
||||||
|
; sets analog port as input
|
||||||
ldi r31, 1 ; means port 0
|
ldi r31, 1 ; means port 0
|
||||||
cpi r24, 0
|
cpi \port, 0
|
||||||
breq end_convert ; = 0 => no need to convert (already set mask to port 0)
|
breq end_convert ; = 0 => no need to convert (already set mask to port 0)
|
||||||
mov r30, r24
|
mov r30, \port
|
||||||
convert:
|
convert:
|
||||||
lsl r31 ; logic shift left ~ r31 * 2
|
lsl r31 ; logic shift left ~ r31 * 2
|
||||||
dec r30
|
dec r30
|
||||||
|
@ -42,52 +49,28 @@ end_convert:
|
||||||
in r30, DDRC
|
in r30, DDRC
|
||||||
and r30, r31 ; applying mask (11111111 and 11110111 = 11110111)
|
and r30, r31 ; applying mask (11111111 and 11110111 = 11110111)
|
||||||
out DDRC, r30
|
out DDRC, r30
|
||||||
|
.endm
|
||||||
|
|
||||||
ret
|
.macro adc_read port, res_high, res_low
|
||||||
|
|
||||||
lm35_init:
|
|
||||||
; args: r24 to r20, where r24 is the lowest
|
|
||||||
subi r24, 14 ; because A0 is D14
|
|
||||||
call analog_pin_mode_input
|
|
||||||
sts lm35_port, r24
|
|
||||||
ret
|
|
||||||
|
|
||||||
float_test:
|
|
||||||
ldi r25, 0b00111110
|
|
||||||
ldi r24, 0b00100000
|
|
||||||
ldi r23, 0b01000000
|
|
||||||
ldi r22, 0b00000000
|
|
||||||
clr r1
|
|
||||||
ret
|
|
||||||
|
|
||||||
blink:
|
|
||||||
ldi r20, 250
|
|
||||||
call delay_n_ms
|
|
||||||
ldi r20, 250
|
|
||||||
call delay_n_ms
|
|
||||||
|
|
||||||
sbi PORTD, LED_PORT ; high
|
|
||||||
ldi r20, 250
|
|
||||||
call delay_n_ms
|
|
||||||
cbi PORTD, LED_PORT ; low
|
|
||||||
|
|
||||||
ret
|
|
||||||
|
|
||||||
lm35_read:
|
|
||||||
; return: r24 to r19, where r24 is the lowest
|
|
||||||
cli ; forbids interruptions
|
|
||||||
|
|
||||||
ldi r30, 0b00000000
|
ldi r30, 0b00000000
|
||||||
sts PRR, r30
|
sts PRR, r30
|
||||||
|
|
||||||
; first two bits are for the ref voltage
|
; first two bits are for the ref voltage
|
||||||
; 11 means using internal 1.1v atmega voltage for adc
|
; 11 means using internal 1.1v atmega voltage for adc
|
||||||
; last three bits are for the analog port number
|
; last three bits are for the analog port number
|
||||||
ldi r30, 0b11000000
|
ldi r30, 0b11000000
|
||||||
lds r24, lm35_port
|
or r30, \port
|
||||||
or r30, r24
|
|
||||||
sts ADMUX, r30
|
sts ADMUX, r30
|
||||||
|
|
||||||
|
; 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!
|
||||||
ldi r30, 0b11000111
|
ldi r30, 0b11000111
|
||||||
sts ADCSRA, r30
|
sts ADCSRA, r30
|
||||||
|
|
||||||
|
@ -99,30 +82,48 @@ wait_adc:
|
||||||
cpi r31, 0
|
cpi r31, 0
|
||||||
brne wait_adc
|
brne wait_adc
|
||||||
|
|
||||||
lds r24, ADCL
|
lds \res_low, ADCL
|
||||||
lds r25, ADCH
|
lds \res_high, ADCH
|
||||||
; clearing unused bits to be sure they're zero
|
; clearing unused bits to be sure they're zero
|
||||||
ldi r31, 0b00000011
|
ldi r31, 0b00000011
|
||||||
and r25, r31
|
and \res_high, r31
|
||||||
|
.endm
|
||||||
|
|
||||||
; r25 high, r24 low - divident and then quotient
|
.macro divw10 divident_high, divident_low
|
||||||
; r30 - res
|
; r30 - res
|
||||||
|
; divident_low - quotient
|
||||||
ldi r30, 0
|
ldi r30, 0
|
||||||
division:
|
division:
|
||||||
cpi r24, 10
|
cpi \divident_low, 10
|
||||||
brlo division_low_end ; <
|
brlo division_low_end ; <
|
||||||
continue_division:
|
continue_division:
|
||||||
sbiw r24, 10
|
sbiw \divident_low, 10
|
||||||
inc r30
|
inc r30
|
||||||
rjmp division
|
rjmp division
|
||||||
division_low_end:
|
division_low_end:
|
||||||
cpi r25, 0
|
cpi \divident_high, 0
|
||||||
brne continue_division
|
brne continue_division
|
||||||
cpi r24, 5
|
cpi \divident_low, 5
|
||||||
brlo not_inc ; <
|
brlo not_inc ; <
|
||||||
inc r30
|
inc r30
|
||||||
not_inc:
|
not_inc:
|
||||||
|
.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
|
||||||
|
|
||||||
|
lds r24, lm35_port
|
||||||
|
adc_read r24, r25, r24
|
||||||
|
|
||||||
|
divw10 r25, r24
|
||||||
mov r24, r30 ; uint8_t return value
|
mov r24, r30 ; uint8_t return value
|
||||||
adiw r24, 2 ; due to LM35 formula (2C to 150C)
|
adiw r24, 2 ; due to LM35 formula (2C to 150C)
|
||||||
|
|
||||||
|
@ -130,17 +131,3 @@ not_inc:
|
||||||
clr r1 ; c requirement
|
clr r1 ; c requirement
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
delay_n_ms:
|
|
||||||
; delay for ~r20 * 1ms. r20, r30, and r31 are modified.
|
|
||||||
; 1 ms ~ 16000 cycles at 16MHz.
|
|
||||||
; The basic loop takes about 5 cycles, so we need about 3000 loops.
|
|
||||||
ldi r31, 3000 >> 8 ; high byte of the 3000
|
|
||||||
ldi r30, 3000 & 255 ; low byte of the 3000
|
|
||||||
delaylp:
|
|
||||||
sbiw r30, 1 ; sub word r30 1
|
|
||||||
brne delaylp ; jne delaylp
|
|
||||||
subi r20, 1
|
|
||||||
brne delay_n_ms
|
|
||||||
ret
|
|
||||||
|
|
|
@ -1,102 +1,28 @@
|
||||||
extern "C" {
|
// Copyright 2021 KoroLion (https://github.com/KoroLion)
|
||||||
void init();
|
|
||||||
void blink();
|
|
||||||
float float_test();
|
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
void lm35_init(uint8_t port);
|
void lm35_init(uint8_t port);
|
||||||
uint8_t lm35_read();
|
uint8_t lm35_read();
|
||||||
|
|
||||||
|
void led_init();
|
||||||
|
void led_enable();
|
||||||
|
void led_disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define UNKNOWN_PIN 0xFF
|
|
||||||
|
|
||||||
uint8_t getPinMode(uint8_t pin)
|
|
||||||
{
|
|
||||||
uint8_t bit = digitalPinToBitMask(pin);
|
|
||||||
uint8_t port = digitalPinToPort(pin);
|
|
||||||
|
|
||||||
// I don't see an option for mega to return this, but whatever...
|
|
||||||
if (NOT_A_PIN == port) return UNKNOWN_PIN;
|
|
||||||
|
|
||||||
// Is there a bit we can check?
|
|
||||||
if (0 == bit) return UNKNOWN_PIN;
|
|
||||||
|
|
||||||
// Is there only a single bit set?
|
|
||||||
if (bit & bit - 1) return UNKNOWN_PIN;
|
|
||||||
|
|
||||||
volatile uint8_t *reg, *out;
|
|
||||||
reg = portModeRegister(port);
|
|
||||||
out = portOutputRegister(port);
|
|
||||||
|
|
||||||
if (*reg & bit)
|
|
||||||
return OUTPUT;
|
|
||||||
else if (*out & bit)
|
|
||||||
return INPUT_PULLUP;
|
|
||||||
else
|
|
||||||
return INPUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
void printPortsStatus() {
|
|
||||||
Serial.print(getPinMode(A0));
|
|
||||||
Serial.print(getPinMode(A1));
|
|
||||||
Serial.print(getPinMode(A2));
|
|
||||||
Serial.print(getPinMode(A3));
|
|
||||||
Serial.print(getPinMode(A4));
|
|
||||||
Serial.print(getPinMode(A5));
|
|
||||||
Serial.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
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!
|
|
||||||
*/
|
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
Serial.begin(9600);
|
Serial.begin(9600);
|
||||||
|
|
||||||
lm35_init(A3);
|
lm35_init(A3);
|
||||||
|
led_init();
|
||||||
// init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
// blink();
|
|
||||||
/*ADMUX = 0b01000011;
|
|
||||||
PRR = 0b00000000;
|
|
||||||
ADCSRA = 0b11000111;
|
|
||||||
while ((ADCSRA & 0b01000000) != 0);
|
|
||||||
short k = ADC;*/
|
|
||||||
|
|
||||||
// max value = 1023
|
|
||||||
// ref voltage is 1.1 V
|
|
||||||
// 1023 - max byte value
|
|
||||||
// +2 to 150, 10 mv/C
|
|
||||||
// k / 255 * 1.1 * 1000 / 10 + 2
|
|
||||||
// Serial.println((float)k * 0.43137254 + 2);
|
|
||||||
// pinMode(A3, OUTPUT);
|
|
||||||
|
|
||||||
/*float *f = malloc(sizeof(f));
|
|
||||||
*f = float_test();
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
Serial.print(((unsigned char*)f)[i]);
|
|
||||||
Serial.print(" ");
|
|
||||||
}
|
|
||||||
Serial.print(" => ");
|
|
||||||
Serial.print(*f, 8);
|
|
||||||
Serial.println();*/
|
|
||||||
|
|
||||||
// uint16_t k = read_temp(A3);
|
|
||||||
// Serial.println((float)k / 1023 * 1.1 * 1000 / 10 + 2);
|
|
||||||
// Serial.println((float)k * 0.10752688 + 2);
|
|
||||||
|
|
||||||
uint8_t t = lm35_read();
|
uint8_t t = lm35_read();
|
||||||
printPortsStatus();
|
if (t >= 30) {
|
||||||
|
led_enable();
|
||||||
|
} else {
|
||||||
|
led_disable();
|
||||||
|
}
|
||||||
|
|
||||||
Serial.println(t);
|
Serial.println(t);
|
||||||
//Serial.print(" vs ");
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user