m820250819LCDHD44780.asm

;; (C) David Vajda
;; 2025-08-19
;; LCD HD44780 Text Output AVR ATMega8

.include "m8def.inc"

;; Pin 1 - VSS - GND
;; Pin 2 - VDD - +5V Versorgungsspannung, sonst VCC - Voltages Currency Collector - VB - Betriebsspannung
;; Pin 3 - VEE - Kontrastspannung
;; Pin 4 - RS - Register Select: Command/Data
;; Pin 5 - RW - Read Write
;; Pin 6 - E - Enable
;; Pin 7 .. Pin 14: D0 .. D7
;; Pin 15: A Anode
;; Pin 16: K Kathode


;; enable: ja, brauchen wir - Enable bit senden, noop noop noop Bit Clear -> nach jedem befehl
;; Read write brauchen wir nicht
;; RS - machen wir 0, fuer commmands, glaube ich, sonst umdrehen und 1 fuer data
;; D4 .. D7 sind im vier bit modus verwendet, dafuer senden wir init 3, 3, 3, 30, 20, ... oder so

;; gepackte und ungepackte nibble in binaerer zaehlweise
;; keine BCD - wegen 0000 ... 1111
;; big-endian und little-endian
;; big-endian per  definition "richtig herum"
;; little-endian "falsch herum"
;; einerseits der controller, atmega8
;; andererseits das lcd - hd44780
;; das hat datenpins - db7 .. db0
;; control bits - control bus - steuerbus, E, RS, W
;; zu den datenbits im vier bit modus, ungepackt, 4 bit
;; beim lcd, ist das - ungepacktes little-endian, db7 .. db4
;; beim atmega8, ungepacktes little-endian, pd0 .. pd3
;; einerseits, port aussen, PORTD entspricht innerhalb register PORD - bit/pin weise
;; da das bit in zwei paketen quasi gemultiplexed uebertragen wird,
;; big-endian in der cpu, little-endian, in dem lcd hd44780
;; stellt sich die frage, ist die uebertragung gemultiplexed, big oder little endian? swap...
;; ==> nebenbei zu der definition zur einstellung allgemeiner parameter, dazu
;; das man ein globales .EQU fuer und high teil bei allen beteiligten einfuehren kann...
;; hier hat sich ein fehler eingeschlichen, der sich korrigieren laesst schreibweisen wie
;; .equ HIGHDATACMDM8 = (r16 >> 4) & 0x0f sind in m8 assembler nicht moeglich.
;; es muessen befehle ausgefuehrt werden
;; aber was moeglich ist, ist zu sagen, die Anzahl der schifts.;;
;; nein auch erst mal bloed, man kann sbis nehmen und so, aber das bringt es nicht
;; jetzt unabhaengig vom multiplexing, wird am PORTD das niedrigere nibble verwendet ...
;; ausserdem: die bit rs, rw, e...
;; sind am PORTD: auf der hoeherwertigen der buchse sind, pin3 .. pin0
;; auf der niederwertigen sind, vcc und gnd
;; inzwishcen kommen, e und rs
;; rw ist nicht notwendig belegt, wenn man nicht liesst
;; dann kommmen zwei frei inzwischen, 7, 8
;; die schaltung angucken...
;; bei den buchsen ist die belegung nicht verpflichtet, rotes kabel an gnd, vermutlich
;; vom grauen 10 bit bus -- umgekehrt, das vcc liegt vermutlich gegenueber, kann das aber
;; westen-osten oder norden-sueden
;; kann aber auch in der mitte liegen, die buchsen sind nicht eindeutig
;; stk500 da liegen vcc und gnd in einer reihe
;; bei dem anderen programmierer, anders ... je nach dem wunsch, wie man die buchse benutzt...
;; habe es herausgefunden:
;; stk500 - https://ww1.microchip.com/downloads/en/DeviceDoc/doc1925.pdf
;; hier ist rot - gnd
;; aber bei meinem neuen programmiergeraet gar nicht
;; die einen verwenden fuer die buchse oder den stecker quadrat in einem eck
;; die anderen zeigen die einkerbung
;; wobei das stk 500 hat ja so keine buchse, dafuer zeichnung
;; dann aber das neue programmiergeraet ...
;; https://www.reichelt.de/de/de/shop/produkt/universal_isp-programer_avr_stm32_esp_lpc-305203?nbc=1
;; Universal ISP-Programer, AVR, STM32, ESP, LPC
;; der hat vcc, wo das stk500 gnd hat, und das gnd ist ebenso gegenueber, aber im sueden, waehrend die kerbe
;; im westen ist..
;; jetzt sehe ich, die zwei freien sind nicht 5 und 6, sondern 7 und 8.
;; und 9 und 10 sind vcc und gnd
;; aber - eben rw - ist einfach mit gnd verbunden - weil wir nicht lesen
;; und - bleiben 5 - 6, rs und e, rs = registerselect cmd/data und e - enable - dasist bit 5

;; was das multiplexing betrifft, wird erst das hoehere uebertragen, big endian ...
;; dann das niedrigere und multiplexing big endian, was auch immer
;; gut.


.equ HD44780_ATMEGA8_PORTX_ENABLE = 5
.equ HD44780_ATMEGA8_PORTX_RS = 6
.equ HD44780INIT0 = 0x03
.equ HD44780INIT1 = 0x03
.equ HD44780INIT2 = 0x03
.equ HD44780INIT3 = 0x02
.equ HD44780INIT4 = 0x20
.equ PORTX = PORTD
.equ DDRX = DDRD
.equ DELAYVAL = 0xff

ldi r16, HIGH (RAMEND)
out SPH, r16
ldi r16, LOW (RAMEND)
out SPL, r16

ldi r16, 0xff
out DDRX, r16


rcall lcdhd44780init
ldi r16, 'h'
rcall lcdhd44780cmdtransmit
ldi r16, 'd'
rcall lcdhd44780cmdtransmit
ldi r16, '4'
rcall lcdhd44780cmdtransmit
ldi r16, '4'
rcall lcdhd44780cmdtransmit
ldi r16, '7'
rcall lcdhd44780cmdtransmit
ldi r16, '8'
rcall lcdhd44780cmdtransmit
ldi r16, '0'
rcall lcdhd44780cmdtransmit
ldi r16, 'a'
rcall lcdhd44780cmdtransmit
ldi r16, 't'
rcall lcdhd44780cmdtransmit
ldi r16, 'm'
rcall lcdhd44780cmdtransmit
loop1: rjmp loop1

lcdhd44780cmdcomplete:
;;sbi set bits in register aber ports
sbi PORTX, HD44780_ATMEGA8_PORTX_ENABLE
nop
nop
nop
cbi PORTX, HD44780_ATMEGA8_PORTX_ENABLE
ret

lcdhd44780init:
rcall delay
ldi r16, HD44780INIT0
rcall lcdhd44780cmdtransmit
rcall delay
ldi r16, HD44780INIT1
rcall lcdhd44780cmdtransmit
rcall delay
ldi r16, HD44780INIT2
rcall lcdhd44780cmdtransmit
rcall delay
ldi r16, HD44780INIT3
rcall lcdhd44780cmdtransmit
rcall delay
ldi r16, HD44780INIT4
rcall lcdhd44780cmdtransmit
rcall delay
ldi r16, 0x0f
rcall lcdhd44780cmdtransmit
ret

lcdhd44780cmdtransmit:
push r16
swap r16
andi r16, 0x0f
sbr r16, HD44780_ATMEGA8_PORTX_RS
out PORTD, r16
rcall lcdhd44780cmdcomplete
pop r16
andi r16, 0x0f
sbr r16, HD44780_ATMEGA8_PORTX_RS
out PORTD, r16
rcall lcdhd44780cmdcomplete
;; swap nibbles, CMD/DATA Entsprechend setzen usw.
ret

lcdhd44780datatransmit:
push r16
swap r16
andi r16, 0x0f
cbr r16, HD44780_ATMEGA8_PORTX_RS
out PORTD, r16
rcall lcdhd44780cmdcomplete
pop r16
andi r16, 0x0f
cbr r16, HD44780_ATMEGA8_PORTX_RS
out PORTD, r16
rcall lcdhd44780cmdcomplete
;; swap nibbles, CMD/DATA Entsprechend setzen usw.
ret


delay:
push r16
ldi r16, DELAYVAL
delay1:
dec r16
breq delay1
pop r16
ret