Professional Documents
Culture Documents
programsAVR 2
programsAVR 2
Start
uppernibble := dbcd_num & $F0
uppernibble >> 4
uppernibble < 10
?
No
Yes
uppernibble := uppernibble * 10
binary_num := dbcd_num & $0F
binary_num < 10
?
No
Yes
binary_num := binary_num + uppernibble
End
:
;-------------------- Double BCD to Binary -------------------;Title: CONV_DBCD_BIN
;Purpose: Conversion of a 1-byte double BCD number (a byte containing BCD digits in
;
both its nibbles) to a 1-byte Binary number
;Input Parameters:
;
dbcd_num: 1-byte double BCD number (a byte containing BCD digits in both its
;
nibbles) to be converted - stored in R16
;Other variables:
;
binary_num: 1-byte Binary number resulting from conversion (output parameter)
;
stored in R17
;
uppernibble: temp storage of upper nibble's binary equivalent - stored in R18
;"Special purpose" Registers used: R1:R0 for the multiplication result
;Exit: "binary_num" holds the binary equivalent of "dbcd_num"
;Errors: one of the BCD digits has ineligible value (is >1001) --> sets T flag
;Comments: ;-------------------.def dbcd_num=R16
.def binary_num=R17
.def uppernibble=R18
;---------CONV_DBCD_BIN:
mov uppernibble, dbcd_num
cbr uppernibble, $0F
(1)
swap uppernibble
cpi uppernibble, 10
brsh inel_bcd_digit
ldi binary_num, 10
(2)
mul uppernibble, binary_num ; upper nibble's binary equivalent is stored in R0
mov binary_num, dbcd_num
cbr binary_num, $F0
cpi binary_num, 10
brsh inel_bcd_digit
add binary_num, R0
clt
ret
inel_bcd_digit:
set
ret
;----- End of subroutine CONV_DBCD_BIN ----.undef dbcd_num
.undef binary_num
.undef uppernibble
:
(1) assembly andi uppernibble,
$F0 (
).
AVR ,
. assembly (
) .
(2) .
.
Start
Is msaschex >$2F
and <$3A?
No
Yes
No
Yes
lsaschex := lsaschex - $30
msaschex << 4
binary_num := msaschex & lsaschex
End
No
Yes
Is lsaschex >$2F
and <$3A?
Is msaschex >$40
and <$47
Is lsaschex >$40
and <$47
No
Yes
lsaschex := lsaschex - $37
:
;-------------------- ASCII Hex to Binary -------------------;Title: CONV_AHEX_BIN
;Purpose: Conversion of a 2 ASCII bytes Hexadecimal number to a 1-byte Binary number
;Input Parameters:
;
lsaschex: ASCII representation of the least significant Hexadecimal digit
;
stored in R16 - altered
;
msaschex: ASCII representation of the most significant Hexadecimal digit
;
stored in R17 - altered
;Other variables:
;
binary_num: 1-byte Binary number resulting from conversion (output parameter)
;
stored in R16
;Exit: "binary_num" holds the binary equivalent of $"msaschex:lsaschex"
;Errors: one of the Hexadecimal digits has ineligible value --> sets T flag
;
(eligible values are: $30-$39 AND $41-$46)
;Comments:
;
- Since the original value of "lsaschex" is altered, the Register that holds it
;
is also used for the "binary_num" variable
;-------------------.def lsaschex=R16
.def msaschex=R17
.def binary_num=R16
;---------CONV_AHEX_BIN:
cpi msaschex, $30
brlo inel_hex_digit
cpi msaschex, $3A
brsh tenorbigger_1
subi msaschex, $30
rjmp check_lsdigit
tenorbigger_1:
cpi msaschex, $41
brlo inel_hex_digit
cpi msaschex, $47
brsh inel_hex_digit
subi msaschex, $37
check_lsdigit:
cpi lsaschex, $30
brlo inel_hex_digit
cpi lsaschex, $3A
brsh tenorbigger_2
subi lsaschex, $30
rjmp combine
tenorbigger_2:
cpi lsaschex, $41
brlo inel_hex_digit
cpi lsaschex, $47
brsh inel_hex_digit
subi lsaschex, $37
combine:
swap msaschex
or binary_num, msaschex
; either OR or ADD have the same result
clt
ret
inel_hex_digit:
set
ret
;----- End of subroutine CONV_AHEX_BIN ----.undef lsaschex
.undef msaschex
.undef binary_num
:
,
ASCII .
Start
bcd_digit < 10
?
No
Yes
Z := led7_table << 1
Z := Z + bcd_digit
led7_code := [Z]
End
led7_code := $30
:
;-------------------- BCD to 7 segment LED display -------------------;Title: CONV_BCD_LED7
;Purpose: Conversion of a 1-byte BCD digit to values that may be outputted to a 7
;
segment LED display for the BCD digit's depiction
;Input Parameters:
;
bcd_digit: 1-byte BCD digit to be depicted - stored in R16
;Other variables:
;
led7_code: the corresponding to "bcd_digit" value that may be outputted to a 7
;
segment LED display (output parameter) - stored in R17
;"Special purpose" Registers used: R31:R30 (Z) for reading from Program Memory
;Exit: "led7_code" holds the 7 segment LED display equivalent of "dbcd_digit"
;Errors:
;
- "dbcd_digit" has ineligible value (is >$09) --> "led7_code"=$30 (depicts 'E')
;Comments:
;
- LED segments are emitting light when the corresponding output pin's value is 0
;
- 7 segment LED code uses 7 bits (the MSb is not used - considered to be 0 in
;
the table's values) ordered in a byte as "_ABCDEFG", connected as following:
;
- A: the upper horizontal segment
_____
;
- B: the right upper segment
| A |
;
- C: the right lower segment
F|
|B
;
- D: the lower horizontal segment
|
|
;
- E: the left lower segment
| G |
;
- F: the left upper segment
E|
|C
;
- G: the middle horizontal segment
|
|
;-------------------D
.def bcd_digit=R16
.def led7_code=R17
led7_table:
.DB $01, $4F, $12, $06, $4C, $24, $60, $0F, $00, $0C
;---------CONV_BCD_LED7:
cpi bcd_digit, $10
brsh inel_bcd_byte
ldi ZL, LOW(led7_table)
ldi ZH, HIGH(led7_table)
lsl ZL
rol ZH
add ZL, bcd_digit
brcc no_carry
inc ZH
no_carry:
lpm led7_code, Z
ret
inel_bcd_byte:
ldi led7_code, $30
ret
;----- End of subroutine CONV_BCD_LED7 ----.undef bcd_digit
.undef led7_code
:
led bit ,
)
1) String concatenation
: ,
. (concat_len).
byte .
:
- temp1: ,
( ,
)
- temp2:
- temp_ad:
debugging:
(i) ?
(ii)
? ( 1-byte )
(iii)
, byte
? ( )
(iv) ? ( )
Start
(i) str2_length = 0 or
str1_length >= concat_length
Yes
End
No
new_length := str1_length + str2_length
(ii)
new_length >
concat_length ?
Yes
No
(iv)counter := new_length - str1_length
str2_ad := str2_ad + 1
(iii)
temp_ad := str1_ad + str1_length + 1
temp_char := [str2_ad]
[temp_ad] := temp_char
counter := counter - 1
No
counter = 0
?
Yes
End
new_length := concat_length
T := 1
:
;-------------------- String concatenation -------------------;Title: STR_CONCAT
;Purpose: Concatenation of two strings, by adding the one at the end of the other,
;
up to a given maximum concatenated string length - the first byte of strings
;
stores its length --> maximum string length=255
;Input Parameters:
;
concat_len: maximum length of the concatenated string - stored in R16
;
str1_stad: starting address of string 1 - stored in R27:R26 (X)
;
str2_stad: starting address of string 2 - stored in R29:R28 (Y) - altered
;Other variables:
;
temp1: temporary storage of str2_len, of str1_len after concatenation, and of
;
num of chars to be added - stored in R17
;
temp2: temporary storage of original str1_len and of char currently transferred
;
stored in R18
;
temp_ad: temporary address to which the copied chars as stored
;
(not necessary, it is employed in order to avoid altering "str1_stad")
;
stored in R31:R30 (Z)
;Exit: - (string 2 or part of it has been added at the end of string 1)
;Errors:
;
ErrorA: string1_length>=concat_length OR string2_length=0 (no changes)
;
--> sets both T and V flags
;
(inappropriate block bounds either for the old or the new location)
;
ErrorB: string1_length+string2_length>concat_length (only a part of string 2 is
;
added at the end of string 1) --> sets T flag, clears V flag
;Comments:
;
- There are no checks for "eligible" bounds of the strings with regard to the
;
allowable (in mega128, data should be stored between $100 and ($1100-a))
;
a: SRAM used locations (for the Stack or other data)
;
- "str2_stad" has been altered at the end of subroutine's code. If it needs to
;
remain unchanged, the "num of chars to be added" before starting adding them
;
(stored at "temp1" at that point) should be stored in an other Register; before
;
subroutine's end, the stored value incremented by 1 should be subtracted from
;
the modified "str2_stad".
;-------------------.def concat_len=R16
.def str1_stad_L=R26 ; XL
.def str1_stad_H=R27 ; XH
.def str2_stad_L=R28 ; YL
.def str2_stad_H=R29 ; YH
.def temp1=R17
.def temp2=R18
.def temp_ad_L=R30 ; ZL
.def temp_ad_H=R31 ; ZH
;---------STR_CONCAT:
ld temp1,
tst temp1
(i)
breq no_concat
ld temp2,
cp temp2, concat_len
(i)
brsh no_concat
clt
; in order to remember if errorB occured or not
add
temp1,
temp2
(iv)
(1) (ii)
brcs partial_concat
; string1_length+string2_length>255 --> >concat_len
cp concat_len, temp1
(ii)
brsh str1newlen_ok
partial_concat:
set
; mark ErrorB
(iv)
mov temp1, concat_len
(2) str1newlen_ok:
st X, temp1
sub temp1, temp2
; temp1 holds the num of chars to be added
movw temp_ad_L, str1_stad_L
(3)
adiw temp_ad_L, 1
; increment by one in order to skip the length's byte
adiw str2_stad_L, 1
add temp_ad_L, temp2
; move temp_ad at the end of string 1
brcc add_char
inc temp_ad_H
add_char:
ld temp2, Y+
(iii)
st Z+, temp2
dec temp1
brne add_char
clv
ret
no_concat:
set
sev
ret
;----- End of subroutine STR_CONCAT ----.undef concat_len
.undef str1_stad_L
.undef str1_stad_H
.undef str2_stad_L
.undef str2_stad_H
.undef temp1
.undef temp2
.undef temp_ad_L
.undef temp_ad_H
:
(1) (C=1)
.
(2)
. temp1 .
.
(3)
. ,
. (
)
16-bit , .
.
Start
(ii)
str1_length = 0 or
str1_length < str2_length or
str2_length = 0
Yes
End
No
(iii) counter1 := str1_length - str2_length
counter2 := str2_length
index := 1
temp1_ad := str1_ad + 1
temp2_ad := str2_ad + 1
temp1_char := [temp1_ad]
temp2_char := [temp2_ad]
temp1_char =
temp2_char ?
Yes
counter2 := counter2 - 1
temp1_ad := temp1_ad + 1
temp2_ad := temp2_ad +1
No
counter2 = 0
?
Yes
End
No
index := index + 1
temp1_ad := str1_ad + index
temp2_ad := str2_ad + 1
counter2 := str2_length
No
(i)
counter1 < 0
?
Yes
counter1 := counter1 - 1
:
;------------------ Find the position of a substring in a string -----------------;Title: SUBSTR_POS
;Purpose: Search for the first occurrence of a substring within a string and return
;
its starting index
;
! the first byte of strings stores its length --> maximum string length=255
;Input Parameters:
;
str1_stad: starting address of string - stored in R17:R16
;
str2_stad: starting address of substring - stored in R19:R18
;Other variables:
;
index: starting index of the first occurrence of the substring within the string
;
(output parameter) - stored in R20
;
counter1: counter of remaining "substring starts" within string - stored in R21
;
(outer loop counter, reduced by one each time the check starting address is
;
incremented by one)
;
counter2: counter of the chars remaining to be matched - stored in R22
;
(inner loop counter, set to substring_length each time the check starting
;
address is incremented by 1 --- when equal to 0 --> successful match)
;
temp1_char: char in string currently processed - stored in R23
;
temp2_char: char in substring currently processed - stored in R24
;
temp_ad1: address of the currently processes string's char
;
stored in R29:R28 (Y)
;
temp_ad2: address of the currently processes substring's char
;
stored in R31:R30 (Z)
;Exit: If the substring is found within the string, "index" holds the starting index
;
of the first occurrence of the substring within the string. Else "index"=0.
;Errors: string_length=0 OR substring_length=0 OR substring_length>string_length
;
--> sets T flag (inappropriate string length)
;Comments:
;
- There are no checks for "eligible" bounds of the strings with regard to the
;
allowable (in mega128, data should be stored between $100 and ($1100-a))
;
a: SRAM used locations (for the Stack or other data)
;-------------------.def str1_stad_L=R16
.def str1_stad_H=R17
.def str2_stad_L=R18
.def str2_stad_H=R19
.def index=R20
.def counter1=R21
.def counter2=R22
.def temp1_char=R23
.def temp2_char=R24
.def temp_ad1_L=R28 ; YL
.def temp_ad1_H=R29 ; YH
.def temp_ad2_L=R30 ; ZL
.def temp_ad2_H=R31 ; ZH
;---------SUBSTR_POS:
movw temp_ad1_L, str1_stad_L
movw temp_ad2_L, str2_stad_L
(1)
ld counter1, Y+
tst counter1
(ii)
breq er_str_len
(1)
ld counter2, Z+
tst counter2
breq er_str_len
sub counter1, counter2
brlo er_str_len
clt
ldi index, 1
inc counter1
char_comp:
(iii)
ld temp1_char, Y+
ld temp2_char, Z+
cp temp1_char, temp2_char
brne inc_check_stad
dec counter2
brne char_comp
ret
inc_check_stad:
(3)
subi counter1, 1
(i)
brcs not_found
(2)
inc index
movw temp_ad1_L, str1_stad_L
add temp_ad1_L, index
brcc contin1
inc temp_ad1_H
contin1:
movw temp_ad2_L, str2_stad_L
ld counter2, Z+
rjmp char_comp
not_found:
clr index
ret
er_str_len:
set
ret
;----- End of subroutine SUBSTR_POS ----.undef str1_stad_L
.undef str1_stad_H
.undef str2_stad_L
.undef str2_stad_H
.undef index
.undef counter1
.undef counter2
.undef temp1_char
.undef temp2_char
.undef temp_ad1_L
.undef temp_ad1_H
.undef temp_ad2_L
.undef temp_ad2_H
(ii)
(i)
(ii)
:
(1)
( ).
(2) index
-.
(3) counter1
.
)
1) AVR102 :BLOCK COPY ROUTINES (Site Atmel)
Start
block_len = 0
?
Yes
No
orig_stad <$100 or
orig_stad > $10FE or
new_stad < $100 or
new_stad > $10FE
(i)
Yes
End
No
(i) (ii)
orig_stad < new_stad
AND
orig_stad + block_len > new_stad
No
temp_stor := [orig_stad]
[new_stad] := temp_stor
orig_stad := orig_stad + 1
new_stad := new_stad + 1
block_len := block_len - 1
No
block_len = 0
?
Yes
End
Yes
:
;-------------------- Move a block of data to a new location -------------------;Title: MOV_BLOCK
;Purpose: Move a block of data to a new SRAM location, given a new starting address
;
! max size of block (potentially=65535) is limited by the type of the memory
;
! used for storing the data. Assuming use of internal SRAM (4KB =$1000 bytes),
;
! for both the initial and the final data storing,
;
! max size = $1000-2-d-a, when orig_stad>new_stad
;
! max size = ($1000-2-a)/2, when orig_stad<new_stad (in order not to overwrite)
;
2: Stack places used for the return address of the subroutine
;
d: absolute distance (in bytes) of transference
;
a: other possible SRAM used places
;Input Parameters:
;
block_len: number of bytes in the block - stored in R25:R24 - altered
;
orig_stad: original starting address of the block - stored in R27:R26 (X)
;
new_stad: new starting address of the block - stored in R29:R28 (Y)
;Other variables:
;
temp_stor: temporary storage of the currently transferred byte - stored in R16
;
temp_stor2: register used coupled with "temp_stor" in order to check for the
;
errors - stored in R17
;Exit: - (the block has been transferred to a new location)
;Errors:
;
ErrorA: orig_stad<$100 OR orig_stad+block_len>RAMEND-2 OR new_stad<$100 OR
;
new_stad+block_len>RAMEND-2 --> sets T flag, clears V flag
;
(inappropriate block bounds either for the old or the new location)
;
ErrorB: orig_stad<new_stad AND orig_stad+block_len>new_stad
;
--> sets both T and V flags
;
(overwriting part of the data before transferred)
;
Empty block : T=V=0
;Comments: ;-------------------.def block_len_L=R24
.def block_len_H=R25
.def orig_stad_L=R26 ; XL
.def orig_stad_H=R27 ; XH
.def new_stad_L=R28 ; YL
.def new_stad_H=R29 ; YH
.def temp_stor=R16
.def temp_stor2=R17
;---------MOV_BLOCK:
tst block_len_L
brne check_AA
tst block_len_H
breq skip_all
; block_len=0, nothing to move
check_AA:
tst orig_stad_H
(2)
breq inconsA
; orig_stad<$100
tst new_stad_H
(2)
breq inconsA
; new_stad<$100
movw temp_stor, new_stad_L
add temp_stor, block_len_L
adc temp_stor2, block_len_H
cpi temp_stor2, $10
; if temp_stor2:temp_stor>$10FE --> ErrorA
brlo new_ad_eligible
; temp_stor2<$10 --> no ErrorA for this check
(2)
brne inconsA
; temp_stor2>$10 --> ErrorA
(3)
cpi temp_stor, $FE
(2)
brsh inconsA
new_ad_eligible:
movw temp_stor, orig_stad_L
add temp_stor, block_len_L
adc temp_stor2, block_len_H
cpi temp_stor2, $10
; if temp_stor2:temp_stor>$10FE --> ErrorA
brlo eligible
; temp_stor2<$10 --> no ErrorA for this check
(2)
brne inconsA
; temp_stor2>$10 --> ErrorA
(3)
cpi temp_stor, $FE
brsh inconsA
(2)
eligible:
cp temp_stor2, new_stad_H ; checking if orig_stad+block_len>new_stad
(ii)
brlo error_free
brne check_BB
cp new_stad_L, temp_stor
brsh error_free
check_BB:
(ii)
cp new_stad_H, orig_stad_H ; checking if orig_stad<new_stad
brlo error_free
(2)
brne inconsB
cp new_stad_L, orig_stad_L
(2)
brsh inconsB
; it covers also the case when new_stad=orig_stad, which
; could be considered as a separate error, since there is no
; meaning to write the data at the same address it is read from,
; but it doesn't create any unpleasant consequences. There is no
; check if new_stad=orig_stad when orig_stad+block_len<=new_stad
error_free:
ld temp_stor, X+
st Y+, temp_stor
sbiw block_len_L, 1
tst block_len_L
brne error_free
tst block_len_H
brne error_free
clt
sev
ret
skip_all:
clt
clv
ret
inconsB:
set
sev
ret
inconsA:
set
clv
ret
;----- End of subroutine MOV_BLOCK ----.undef block_len_L
.undef block_len_H
.undef orig_stad_L
.undef orig_stad_H
.undef new_stad_L
.undef new_stad_H
.undef temp_stor
.undef temp_stor2
:
(1) 16-bit
bytes ( 65535),
SRAM. 4 KB SRAM,
:
- $1000-2-d-a, orig_stad>new_stad
- ($1000-2-a)/2, orig_stad<new_stad (
), :
2:
d: ( bytes)
a: SRAM
(2) . ( )
(ErrorA)
(ErrorB).
,
orig_stad
new_stad.
(3) $10FE ,
.
(SP),
.
SP ,
SP ( ISR).
.
(4) orig_stad new_stad ( byte
), block_len.
orig_stad new_stad .
(
).
.
Start
(i)
numof_cols = 0
?
Yes
No
(i)
arst_ad < $100
?
Yes
End
No
elem_ad = elem_row * numof_cols
elem_ad = elem_ad + elem_col
(i)
elem_ad < RAMEND - a
?
Yes
Flag correct result
End
No
(1)
(2)
(2)
(3)