📜 ⬆️ ⬇️

CMD on ATmega16

Spoiler : this article does not squeeze nostalgic tears.

Having decided not so long ago to get acquainted closer (after the Arduino) with microcontrollers in general
and with ATmega microcontrollers in particular, I quickly realized that just reading about MK,
run the code in the emulator, “blinking LED” - this is somehow not the case. So I decided
"Gash" any - even if useless - project, and deal with everything
already along the way. Microprocessor labs came to mind
and the training stand on which these works were performed - the so-called educational microprocessor
set (UMK), which we called simply “Umka”.

About CMD


So, if you do not go into details (if you go - then the links below), then
"Umka" is a microcomputer based on microprocessor K580IK80A, produced in the 80s
of the last century (I was also lucky to work with him in the not-quite-distant 2009)
is a weighty such box. More information about the story "Umok"
and so on can be found on the second link below. This is how it looks.
')

(The photo is brazenly taken from the first link below; more photos are from the same
link)

What is there: indication of data buses and addresses, indication of the processor status register,
display to display the contents of memory cells and input data, input buttons
data. The two columns of buttons to the left are the so-called directives sewn into “Umka”
“Monitor” programs - they became the goal of my project (directives, not buttons).
Briefly about directives. There is nothing special.
"P" - view the contents of the memory cell: enter the address of the cell, see what is there
lies, if desired - write another value.
"WG" - view the contents of the registers: similar to viewing the contents of the cells. In my
"Version" of this directive is missing: it is not particularly necessary, because in
ATmega RAM, general registers and peripheral registers are located in
address space, and it is assumed that they can be accessed through
Directive "P".
“CS” - calculation of the checksum of the data array: enter the address of the beginning of the array,
the final address of the array, the sum of the contents of the cells of the array is displayed.
“” - filling the memory array with a constant: enter the starting address, enter the ending
address of the array, enter the variable - the cells of the array are filled with this variable.
“PM” - relocation of the memory array: enter the starting address of the array being moved
memory, enter its final address, enter the starting address of the array - array
moves to the memory area starting with the entered allocation address.
The directive "ST" - the implementation of the user program - I missed, more on that below.
The “VP” button is the execution of the directive, the "_" button separates the variables as they are entered, "SB" - the button
reset. Read more about entering and executing directives here.

sfrolov.livejournal.com/136290.html - photo CMD, memories, impressions.
www.computer-museum.ru/histussr/umk_sorucom_2011.htm - a bit of history.

What was planned


The aim of my project was to create a device capable of fulfilling these directives and
display information on the display, a kind of lite-version of "Umki" (well, very, very lite).
What was used in the project:
1. The ATmega16 microcontroller. The program is written in assembly language in AVRStudio.
2. Matrix keyboard for entering values. I found the code for working with the keyboard
here (thanks to the author), then just rewrote it in assembler. Since RAM ATmega16
limited to the address $ 045F, then the last three digits are entered. By the way, data / addresses
are entered and displayed in hexadecimal format.
3. LCD display 16x2 on the controller HD44780. Understanding the display helped these
Two articles - here and here (thanks to the authors), the datasheet helped to initialize the display correctly.
4. Simple buttons for directives. Another button was also added - “Enter” (on
photo it with an arrow): needed to confirm the input of each digit of the address or data
- a kind of protection from the chatter of the contacts of the matrix keyboard (without which it is quite possible
it was a cost, but a clever idea, as they say, comes afterwards).

What is the result


It was possible to achieve everything that was planned: you can view and change
contents of RAM and MK registers, write a constant to an array of cells, count
checksum of the array, move the array of cells (here is the entertainment * sarcastic *);
writing / moving an array somewhere for $ 0440 (approximately) makes a regular
chaos in the stack area. You can perform as many as six items of the first laboratory work from
Workshop on the link above.
Judging by the information found, the “Monitor” program, wired into “Umka”, occupies 1 Kb.
One of the tasks was to put the program in 1 KB, which was successfully (even with
reserve), but because of the LCD-display and the desire to make the code more informative
almost doubled.
This “Umka” (professional edition) allowed you to write your program on
microprocessor assembler K580IK80A, recording in memory the codes of the relevant commands,
and then perform it either stepwise or cyclically. I do not know how it was
implemented in Umka, and the solution does not seem obvious to me, so this option in
there is no project (for a start, however, the directives were enough for me), I will gladly accept
proposals for the implementation of this. For this, I affectionately nicknamed the resulting device "Wit."



This is the code
.include "m16def.inc"
.device ATmega16
.def count = r18; r18 - counter
.def mode = r19; r19 - signs of modes
.def buf = r25; to enter values
.def rLCD = r22; for working with LCD
.def rKey = r20; keyboard and trivial values

; LCD commands
.equ off = 0b00001000; off
.equ clrSc = 0b00000001; clear
.equ config = 0b00111000; 8bit, 2 lines
.equ incr = 0b00000110; addr + (increase address, static screen)
.equ on = 0b00001100; on
.equ right = 0b00010100; right shift
.qu down = 0b11000000; go to the second line
.qu up = 0b10000000; on the first line
.equitor = 0b00001111; flashing cursor
.equ noCursor = 0b00001100
.equ left = 0b00010000; to the left

; LCD data (port D)
.equ _dp = DDRD
.equ _dpo = PORTD
.equ _dpi = PIND

; LCD control (port C)
.equ _cp = DDRC
.equ _cpo = PORTC
.equ rs = 0
.equ rw = 1
.equ e = 7

; keyboard (port A)
.equ _mp = DDRA
.equ _mpi = PINA
.equ _mpo = PORTA

; directives (port B)
.equ BUT = PINB
.equ BUTddr = DDRB
.equ BUTp = PORTB
.equ P = 0; button P (view / change the contents of memory)
.equ quit = 1; output
. equ exe = 2; VP button (execution)
.equ enter = 3; enter button
.equ space = 4; "_" button
.ququ CF = 5; button ZK (filling constant)
.equ CS = 6; COP button (checksum)
.equ AM = 7; PM button (array moving)
; T flag - data entry mode

; ======================= Macro to poll the matrix keyboard ====================
.macro matrix
rcall _exit
ldi rKey, 0
ldi r16, 0xff; load units in r16
cbi _mpo, @ 0; clear the bit corresponding to the column
out _mpo, r16; units in portd
in r16, _mpi; read port D data register
cpi r16, @ 1
breq ein
cpi r16, @ 2
breq zwei
cpi r16, @ 3
breq drei
cpi r16, @ 4
breq vier
sbi _mpo, @ 0; set the bit corresponding to the column (return to the original state)
rjmp @ 9; if none of the buttons in the column were pressed,
; then go to the label - the macro with the parameters of the next column or at the beginning of the survey

ein:
ldi rKey, @ 5; loading the rKey value corresponding to the button pressed
ldi rLCD, @ 5; load the same value for display
rcall _BF
rcall _charInput
sbi _mpo, @ 0; set the bit corresponding to the column (return to the original state)
rjmp _check; go to view label

zwei:
ldi rKey @ 6
ldi rLCD, @ 6
rcall _BF
rcall _charInput
sbi _mpo, @ 0
rjmp _check

drei:
ldi rKey @ 7
ldi rLCD @ 7
rcall _BF
rcall _charInput
sbi _mpo, @ 0
rjmp _check

vier:
ldi rKey @ 8
ldi rLCD @ 8
rcall _BF
rcall _charInput
sbi _mpo, @ 0
rjmp _check
.endmacro

.cseg

.org 0

; stack
ldi r16, Low (RAMEND)
out SPL, r16
ldi r16, High (RAMEND)
out SPH, r16

sbi _cp, 0; rs
sbi _cp, 1; rw
sbi _cp, 7; e

; port initialization
ldi r16,0b00001111
out _mp, r16; DDRA - input
ldi r16, 0b11110000
out _mpo, r16; with a suspender

ldi r16, 0x00
out BUTddr, r16; DDRB - input
ldi r16, 0xff
out BUTp, r16; with a suspender

; display initialization
rcall altInit

; ================================= main loop ============== ================
go:
rcall _resetLCD
ldi xl, 0x00
ldi xh, 0x00
ldi yl, 0x00
ldi yh, 0x00
ldi zl, 0x00
ldi zh, 0x00
clt
clc
clh
clr mode
clr buf
ldi count, 1

; ========================== operation mode check ==================== ========
modeCheck:
sbis BUT, P; P mode
rjmp _P
sbis BUT, CF; ZK mode
rjmp _setConst
sbis BUT, CS; COP mode
rjmp _setSum
sbis BUT, AM; PM mode
rjmp _setArray
rjmp modeCheck

_setConst:
sbr mode, 1; setting the sign of the LC mode
; display mode information
rcall _clear
rcall _labelWrite; write
rcall _labelSpace; _
rcall _labelConst; const
rcall _point ;.
rcall _down
rcall _labelAddr; address
rcall _labelOne; one
rcall _colon ;:
rcall _labelZero; 0
rcall _cursor
rjmp scan

_setSum:
sbr mode, 5; setting the feature of the COP mode
rcall _clear
rcall _labelSum; checksum
rcall _down
rcall _labelAddr; address
rcall _labelOne; one
rcall _colon ;:
rcall _labelZero; 0
rcall _cursor
rjmp scan

_setArray:
sbr mode, 9; setting feature of PM mode
rcall _clear
rcall _mArray
rcall _down
rcall _labelAddr
rcall _labelOne
rcall _colon
rcall _labelZero
rcall _cursor
rjmp scan

_check :; after entering the number - here
sbrc mode, 0; check mode
rjmp _const; if ZK, KS or PM, then here
rjmp _view

_P :; P mode
rcall _clear
rcall _browse
rcall _labelSpace
rcall _labelZero
rcall _cursor

scan :; poll matrix keyboard
rcall _exit
rcall _cursor
matrix 0, 0b11101110, 0b11011110, 0b10111110, 0b01111110, 3, 7, 11, 15, next

next:
matrix 1, 0b11101101, 0b11011101, 0b10111101, 0b01111101, 2, 6, 10, 14, next1

next1:
matrix 2, 0b11101011, 0b11011011, 0b10111011, 0b01111011, 1, 5, 9, 13, next2

next2:
matrix 3, 0b11100111, 0b11010111, 0b10110111, 0b01110111, 0, 4, 8, 12, scan

rjmp scan
; ================================================= ========================

; ========================== waiting to press the enter button =================== =
_view:
brts _input; go to input if the T-flag is set (i.e. data entry mode)
rcall _exit
sbic BUT, enter; if the enter button is not pressed,
rjmp _view; then we close the loop and wait for pressing the EXIT, reset or input buttons
cpi count, 1; comparison of the counter value: if 1,
breq one; the first digit is entered
cpi count, 2; if 2,
breq two; then the second is introduced
cpi count, 3; if 3,
breq three; then the last digit is entered
rjmp _view

; enter the first digit of the address
one:
mov xh, rKey
inc count
rjmp scan; transition to survey mat. clav

; Enter the second digit of the address
two:
mov xl, rKey
swap xl
inc count
rjmp scan

; enter the third digit of the address
three:
rcall _noCursor; the cursor is not needed
add xl, rKey
inc count
rjmp finish; after entering the third digit, go to finish
; ================================================ =================================

; ================================== input mode ============= ===================
_input:
rcall _exit
sbic BUT, enter; if the input button is pressed, then jump over to compare the counter
rjmp _input
cpi count, 1; if the counter is 1, then the first digit is entered
breq first
cpi count, 2; if 2, then the second
breq second
rjmp _input

first :; input first digit
mov buf, rKey
swap buf
inc count
rjmp scan

second :; enter second digit
rcall _noCursor
add buf, rKey
inc count
rjmp _waitFor
; ================================================ ================================

; ======================= waiting after entering the third digit ===================== =
finish :; go here after entering the third digit
brts link; if the T-flag is set, then this is the data entry mode, go to scan
rcall _exit
sbis BUT, exe; EXIT button
rjmp view; go to view if exp.
sbic BUT, space; "_" button
rjmp finish
ldi count, 1; reset the counter
set; set the T-flag in the status register
; display “WRITE DATA” in the first line
rcall _clear
rcall _labelWrite
rcall _labelSpace
rcall _labelData
; go to the second one
rcall _down
; set the cursor
rcall _cursor
rjmp finish
link:
rjmp scan
; ================================================= ==========================

; =============== viewing the contents of a cell (after clicking the EX button -> here)
view:
; output of the inscription "BROWSE XXXX"
rcall _clear
rcall _browse; Brose
rcall _labelSpace; _
mov rLCD, xh; first XX
rcall _charFromMemory
mov rLCD, xl; second XX
rcall _charFromMemory
; displaying the contents of a memory cell
rcall _noCursor
rcall _down
ld rLCD, X +
rcall _charFromMemory
view1:
rcall _exit
ldi count, 1
sbic BUT, space; if the "_" button is pressed, then go to the cell with the address 1 more
rjmp view1
rcall _delay1
rjmp view
; ================================================= ===========================

; ========================= Writing a value to a memory cell ==================== ===
input:
st X, buf
clt; clear T-flag after data entry mode is completed
rjmp go
; ================================================ =================================

; ========== waiting for clicking EX. or "_" to continue typing ===============
_waitFor :; after entering the second digit (data) - here
sbrc mode, 0
rjmp _WC
rcall _exit
sbis BUT, exe; if EXIT is pressed, then go to input
rjmp input
sbic BUT, space; if "_" is pressed,
rjmp _waitFor; then jump over it,
st X +, buf; write the data entered into memory
ldi count, 1; reset the counter
rcall _clear
rcall _labelWrite
rcall _labelSpace
rcall _labelData
rcall _down
rjmp scan

_WC:
rcall _exit
sbic BUT, exe
rjmp _WC
rjmp _execConst
; ================================================= ============================

; =============================== LC mode (filling with a constant) ============= =====
_const:
brts to_input
rcall _exit
sbic BUT, enter; if the enter button is not pressed,
rjmp _const; then we close the loop and wait for pressing the EXIT, reset or input buttons
cpi count, 1; comparison of the counter value: if 1,
breq _one; the first digit is entered
cpi count, 2; if 2,
breq _two; then the second is introduced
cpi count, 3; if 3,
breq _three; then the last digit is entered
rjmp _const; in cycle
to_input:
rjmp _input

; enter the first digit of the first address
_one:
sbrc mode, 4; if the 2nd bit is set (sign of entering the third address),
rjmp _ad31; <- move here
sbrc mode, 1; if the 1st bit in r19 is not set (sign of entering the second address),
rjmp inpConst1; then we skip it
mov xh, rKey
inc count
rjmp scan
; enter the first digit of the second address
inpConst1:
mov yh, rKey
inc count
rjmp scan

; enter the second digit of the first address
_two:
sbrc mode, 4; if the 2nd bit is set (sign of entering the third address),
rjmp _ad32; <- move here
sbrc mode, 1; if the 1st bit is set in r19 (sign of entering the second address),
rjmp inpConts2; then go to inpConst1
mov xl, rKey
swap xl
inc count
rjmp scan
; enter the second digit of the second address
inpConts2:
mov yl, rKey
swap yl
inc count
rjmp scan

; enter the third digit of the first address
_three:
sbrc mode, 4; if the 2nd bit is set (sign of entering the third address),
rjmp _ad33; <- move here
sbrc mode, 1
rjmp inpConst3
rcall _noCursor
add xl, rKey; rKey -> to the junior tetra mla. byte reg. X pairs
inc count
rjmp constEnd; after entering the third axis, go to constEnd
; enter the third digit of the second address
inpConst3:
rcall _noCursor
add yl, rKey
inc count
rjmp constEnd

constEnd :; go here after entering the third digit
brts _link; if the T-flag is set, then this is the data entry mode, go to scan
sbrc mode, 1; if the sign of entering the second address is set,
rjmp _ad2; then here
sbrc mode, 2; if the “COP” feature is set,
rjmp _ifCheckSum; then here
sbrc mode, 3; if the sign of the PM mode is set,
rjmp _ifArray; then here
rcall _exit
sbic BUT, space; if the "_" button is pressed,
rjmp constEnd; then jump over it,
ldi count, 1; reset the counter
sbr mode, 3; in r19 is now 0b00000011 (sign of entering the second address in the LC)
; refining the screen content
; address2
rcall _down
rcall _labelAddr
rcall _labelTwo
rcall _colon
rcall _labelZero
rcall _labelSpace
rcall _labelSpace
rcall _labelSpace
rcall _left
rcall _left
rcall _left
rjmp scan

_ad2 :; go here after entering the second address
sbrc mode, 2; if the sign of "COP" is set, then go
rjmp _toCheckSum
sbrc mode, 3; if the sign "PM" is set,
rjmp _toArray; <- here
rcall _exit
sbic BUT, space; if the "_" button is pressed,
rjmp _ad2; then miss it
ldi count, 1; reset the counter
set; and set the sign of data entry
; refining the screen content
; const
rcall _down
rcall _labelConst
rcall _colon
rcall _labelSpace
rcall _labelSpace
rcall _labelSpace
rcall _labelSpace
rcall _labelSpace
rcall _labelSpace
rcall _labelSpace
rcall _left
rcall _left
rcall _left
rcall _left
rcall _left
rcall _left
rcall _left
rjmp constEnd; -> to cycle

_link:
rjmp scan

_ifCheckSum :; A branch from “” to “”, if the 2nd bit in mode is set
sbic BUT, space
rjmp _ifCheckSum
ldi count, 1
; refining the screen contents:
; address2
rcall _down
rcall _labelAddr
rcall _labelTwo
rcall _colon
rcall _labelZero
rcall _labelSpace
rcall _labelSpace
rcall _labelSpace
rcall _left
rcall _left
rcall _left
sbr mode, 7; sign of entering the second address "KS"
rjmp scan

_toCheckSum :; on performance of "KS"
rcall _exit
sbic BUT, exe; if “EX” is pressed, then go to “COP”
rjmp _toCheckSum
ldi rKey, 0x00; pre-zero the registers used
ldi buf, 0x00
rjmp _SUM

_ifArray :; branch from "KS" to "PM"
sbic BUT, space
rjmp _ifArray
ldi count, 1
; refining the screen content
; address2
rcall _down
rcall _labelAddr
rcall _labelTwo
rcall _colon
rcall _labelZero
rcall _labelSpace
rcall _labelSpace
rcall _labelSpace
rcall _left
rcall _left
rcall _left
sbr mode, 11
rjmp scan

_toArray :; transition after entering the second address
ldi count, 1
sbr mode, 27; 0b00011011 -> r19 - sign of entering the third address
rcall _exit
sbic BUT, space
rjmp _toArray
; refining the screen content
; address3
rcall _down
rcall _labelAddr
rcall _labelThree
rcall _colon
rcall _labelZero
rcall _labelSpace
rcall _labelSpace
rcall _labelSpace
rcall _left
rcall _left
rcall _left
rjmp scan

; first digit of the third address (PM)
_ad31:
mov zh, rKey
inc count
rjmp scan

; second digit of the first address
_ad32:
mov zl, rKey
swap zl
inc count
rjmp scan

; third digit of the third address
_ad33:
rcall _noCursor
add zl, rKey
inc count
rjmp _arrayEnd

; waiting for pressing the VI after entering the third address
_arrayEnd:
rcall _exit
sbic BUT, exe
rjmp _arrayEnd
ldi buf, 0x00; pre-zeroing buf
rjmp _execArray

; ============================== ZK implementation ================= ================
_execConst:
; first comparison
_ccp1 :; yh> xh?
cp yh, xh
brlo _errConst; if yh <xh
breq _eq1; if yh = xh
rjmp _ccp2

_eq1 :; if yh = xh
cp yl, xl; yl> xl?
brlo _errConst; if yl <xl

; if the first number is less than the second,
; then go to the second comparison
_ccp2 :; if yh> xh
cp yh, xh; yh> xh?
breq _ccp22; if yh = xh
st X +, buf
rjmp _ccp2

_ccp22 :; if yh = xh
cp yl, xl; yl> xl?
brlo _end; if xl> yl
st X +, buf
rjmp _ccp22

_errConst :; “ERROR” if the first number is more than the second
rcall _clear
rcall _labelWrite
rcall _labelSpace
rcall _labelConst
rcall _point
rcall _down
rcall _noCursor
rcall _labelErr
rjmp _wait

_end :; output
rjmp go

; ============== calculation of the checksum of the array =======================
_SUM:
; first comparison
_scp1 :; yh> xh?
cp yh, xh
brlo _errSum; if yh <xh
breq _eq2; if yh = xh
rjmp _scp2

_eq2 :; if yh = xh
cp yl, xl; yl> xl?
brlo _errSum; if yl <xl

; if the first number is less than the second,
; then go to the second comparison
_scp2 :; if yh> xh
cp yh, xh; yh> xh?
breq _scp22; if yh = xh
rcall _exCS
brcs _overflow
rjmp _scp2

_scp22 :; if yh = xh
cp yl, xl; yl> xl?
brlo _showSum; if xl> yl
rcall _exCS
brcs _overflow
rjmp _scp22

_showSum :; display checksum
rcall _clear
rcall _labelSum
rcall _down
rcall _noCursor
mov rLCD, rKey
rcall _charFromMemory
_wait:
rcall _exit
rjmp _wait

_errSum :; “ERROR” if the first number is more than the second
rcall _clear
rcall _labelSum
rcall _down
rcall _noCursor
rcall _labelErr
rjmp _wait

_overflow :; when exceeding COP 255 - here
; dumping of flags of transfer and half transfer (just in case)
clh
clc
ldi rKey, 0xff; if the COP is greater than 0xFF, then FF is displayed on the screen.
rjmp _showSum

_exCS :; subroutine implementation of the COP
ld buf, X +
add rKey, buf
; rcall _cpixl
ret

; ============================ Array Motion ==================== ===========
_execArray:
; first comparison
_acp1 :; yh> xh?
cp yh, xh
brlo _errArr; if yh <xh
breq _eq3; if yh = xh
rjmp _acp2

_eq3 :; if yh = xh
cp yl, xl; yl> xl?
brlo _errArr; if yl <xl

; if the first number is less than the second,
; then go to the second comparison
_acp2 :; if yh> xh
cp yh, xh; yh> xh?
breq _acp22; if yh = xh
rcall _exMA
rjmp _acp2

_acp22 :; if yh = xh
cp yl, xl; yl> xl?
brlo _end; if xl> yl
rcall _exMA
rjmp _acp22

_errArr :; “ERROR” if the first number is more than the second
rcall _clear
rcall _mArray
rcall _down
rcall _noCursor
rcall _labelErr
rjmp _wait

_exMA :; subroutine execution PM
ld rKey, X +
st Z +, rKey
ret
; ================================================= =================

_exit:
sbis BUT, quit; if the exit button is pressed,
rjmp go; then exit from go mode
ret
; ================================================= ==================

; work with the screen

; LCD initialization
altInit:
rcall _delay1
ldi rLCD, config; display setting: 8 bits, 2 lines, 5x8
rcall _cWrite

rcall _delay1
ldi rLCD, on; turn on the display
rcall _cWrite

rcall _delay1
ldi rLCD, clrSc; screen cleaning
rcall _cWrite

rcall _delay1
ldi rLCD, incr; increase of the address, the screen is static
rcall _cWrite
ret

; busy bit check
_BF:
rcall _portIn; input data port
rcall _modeB; command reading mode
_loop:
sbi _cpo, e
rcall _delay
cbi _cpo, e
in r24, _dpi; read data bus
andi r24, 0x80; check 7th bit
brne _loop
ret

; delay
_delay:
ldi r23, 20
_del:
dec r23
brne _del
ret

// more delay
_delay1:
ldi r24, 0xff; 255
_d:
ldi r23, 0xff; 255
_cmp_d:
dec r23
brne _cmp_d
dec r24
brne _cmp_d
ret

; team record
_cWrite:
rcall _modeC
rcall _portOut
out _dpo, rLCD
rcall _delay
cbi _cpo, e
ret

; data record
_dWrite:
rcall _modeD
rcall _portOut
out _dpo, rLCD
rcall _delay
cbi _cpo, e
ret

; data output port
_portOut:
ldi r23, 0xff
out _dp, r23
ret

; data port input with a suspender
_portIn:
ldi r23, 0x00
out _dp, r23
ldi r23, 0xff
out _dpo, r23
ret

; command record mode
_modeC:
cbi _cpo, rw
cbi _cpo, rs
sbi _cpo, e
ret

; data recording mode
_modeD:
sbi _cpo, rs
cbi _cpo, rw
sbi _cpo, e
ret

; standby BF
_modeB:
sbi _cpo, rw; reading
cbi _cpo, rs; teams
ret

; generation of character code when entering addresses and data
_charInput:
cpi rLCD, 0x0a; compare with 10
brge _grt; if more, then go to _grtA
rcall _lstA
rjmp _return
_grt:
rcall _grtA
_return:
ret

_lstA:
ldi r21, 0x30; if less
add rLCD, r21; then add 48
rcall _dWrite; write to LCD
ret

_grtA :; if the number from A ... F
ldi r21, 0x37; 55 - add to rLCD to get character code
add rLCD, r21;
rcall _dWrite; write to LCD
ret

; character formation when reading from memory
; works through rLCD
_charFromMemory:
push rLCD; sent to the stack
; high byte formation
andi rLCD, 0xf0; clear junior nibble
swap rLCD; swap nibbles
rcall _BF
rcall _charInput
; high byte formation
pop rLCD; get out of the stack
andi rLCD, 0x0f; clear senior nibble
rcall _BF
rcall _charInput
ret

; ========================================== all sorts of inscriptions and screen settings === ============================

; "-"
_none:
; rcall _up
ldi rLCD, 0x2D
rcall _BF
rcall _dWrite
ret

; on the second line
_down:
ldi rLCD down
rcall _BF
rcall _cWrite
ret

; the inscription "BROWSE"
_browse:
ldi rLCD, 0x42; B
rcall _BF
rcall _dWrite
ldi rLCD, 0x52; R
rcall _BF
rcall _dWrite
ldi rLCD, 0x4f; O
rcall _BF
rcall _dWrite
ldi rLCD, 0x57; W
rcall _BF
rcall _dWrite
ldi rLCD, 0x53; S
rcall _BF
rcall _dWrite
ldi rLCD, 0x45; E
rcall _BF
rcall _dWrite
ret

; the inscription "MOVE ARRAY"
_mArray:
ldi rLCD, 0x4d; M
rcall _BF
rcall _dWrite
ldi rLCD, 0x4f; O
rcall _BF
rcall _dWrite
ldi rLCD, 0x56; V
rcall _BF
rcall _dWrite
ldi rLCD, 0x45; E
rcall _BF
rcall _dWrite
rcall _labelSpace
ldi rLCD, 0x41; A
rcall _BF
rcall _dWrite
ldi rLCD, 0x52; R
rcall _BF
rcall _dWrite
ldi rLCD, 0x52; R
rcall _BF
rcall _dWrite
ldi rLCD, 0x41; A
rcall _BF
rcall _dWrite
ldi rLCD, 0x59; Y
rcall _BF
rcall _dWrite
ret

; the inscription "DATA"
_labelData:
ldi rLCD, 0x44; D
rcall _BF
rcall _dWrite
ldi rLCD, 0x41; A
rcall _BF
rcall _dWrite
ldi rLCD, 0x54; T
rcall _BF
rcall _dWrite
ldi rLCD, 0x41; A
rcall _BF
rcall _dWrite
ret

; the inscription "WRITE"
_labelWrite:
ldi rLCD, 0x57; W
rcall _BF
rcall _dWrite
ldi rLCD, 0x52; R
rcall _BF
rcall _dWrite
ldi rLCD, 0x49; I
rcall _BF
rcall _dWrite
ldi rLCD, 0x54; T
rcall _BF
rcall _dWrite
ldi rLCD, 0x45; E
rcall _BF
rcall _dWrite
ret

; the inscription "CONST"
_labelConst:
ldi rLCD, 0x43; C
rcall _BF
rcall _dWrite
ldi rLCD, 0x4f; O
rcall _BF
rcall _dWrite
ldi rLCD, 0x4e; N
rcall _BF
rcall _dWrite
ldi rLCD, 0x53; S
rcall _BF
rcall _dWrite
ldi rLCD, 0x54; T
rcall _BF
rcall _dWrite
ret

; the inscription "ADDRESS"
_labelAddr:
ldi rLCD, 0x41; A
rcall _BF
rcall _dWrite
ldi rLCD, 0x44; D
rcall _BF
rcall _dWrite
ldi rLCD, 0x44; D
rcall _BF
rcall _dWrite
ldi rLCD, 0x52; R
rcall _BF
rcall _dWrite
ldi rLCD, 0x45; E
rcall _BF
rcall _dWrite
ldi rLCD, 0x53; S
rcall _BF
rcall _dWrite
ldi rLCD, 0x53; S
rcall _BF
rcall _dWrite
ret

; the inscription "CHECKSUM"
_labelSum:
ldi rLCD, 0x43; C
rcall _BF
rcall _dWrite
ldi rLCD, 0x48; H
rcall _BF
rcall _dWrite
ldi rLCD, 0x45; E
rcall _BF
rcall _dWrite
ldi rLCD, 0x43; C
rcall _BF
rcall _dWrite
ldi rLCD, 0x4b; K
rcall _BF
rcall _dWrite
ldi rLCD, 0x53; S
rcall _BF
rcall _dWrite
ldi rLCD, 0x55; U
rcall _BF
rcall _dWrite
ldi rLCD, 0x4d; M
rcall _BF
rcall _dWrite
ret

; the inscription "ERROR"
_labelErr:
ldi rLCD, 0x45; E
rcall _BF
rcall _dWrite
ldi rLCD, 0x52; R
rcall _BF
rcall _dWrite
ldi rLCD, 0x52; R
rcall _BF
rcall _dWrite
ldi rLCD, 0x4f; O
rcall _BF
rcall _dWrite
ldi rLCD, 0x52; R
rcall _BF
rcall _dWrite
ret

; "0"
_labelZero:
ldi rLCD, 0x30
rcall _BF
rcall _dWrite
ret

; "one"
_labelOne:
ldi rLCD, 0x31
rcall _BF
rcall _dWrite
ret

; "2"
_labelTwo:
ldi rLCD, 0x32
rcall _BF
rcall _dWrite
ret

; "3"
_labelThree:
ldi rLCD, 0x33
rcall _BF
rcall _dWrite
ret

; space
_labelSpace:
ldi rLCD, 0x20
rcall _BF
rcall _dWrite
ret

; clear both lines
_clear:
ldi rLCD, clrSc
rcall _BF
rcall _cWrite
ret

; cleaning the screen and displaying the "-" character
_resetLCD:
rcall _clear
rcall _noCursor; no cursor
rcall _BF
; rcall _cWrite
rcall _none
ret

; setting the flashing cursor
_cursor:
ldi rLCD, cursor
rcall _BF
rcall _cWrite
ret

; disable cursor
_noCursor:
ldi rLCD, noCursor
rcall _BF
rcall _cWrite
ret

; "."
_point:
ldi rLCD, 0x2e
rcall _BF
rcall _dWrite
ret

; ":"
_colon:
ldi rLCD, 0x3a
rcall _BF
rcall _dWrite
ret

; cursor right
_right:
ldi rLCD, right
rcall _BF
rcall _cWrite
ret

; left shift
_left:
ldi rLCD, left
rcall _BF
rcall _cWrite
ret

And this is a video that is used to modify and view the contents of a memory cell and the cells that follow it.

Source: https://habr.com/ru/post/262463/


All Articles