This Assembler program will display a message using 6 character chunks on the Butterfly 6 character LCD Screen. Program is approx 430 bytes.
;------------------------------------------;
; HELLO WORLD (REVISITED) ;
; ======================= ;
; ;
; AUTHOR: DANIEL J, DOREY AKA RETRODAN ;
; 05-OCT-09: CREATED LAST UPDATE:20-OCT-09 ;
; ;
; DISPLAYS 6-CHAR STRINGS ON LCD SCREEN ;
;------------------------------------------;
.NOLIST
.INCLUDE "M169DEF.INC" ;BUTTERFLY DEFS
.LIST
;---------------------------------:
; RENAME/DEFINE WORKING REGISTERS ;
;---------------------------------;
.SET CHR6BUF = 2 ;6 CHAR BUFFER IS [R2,R3,R4,R5,R6,R7]
.DEF ZERO = R8
.DEF THREE = R10
.DEF T1 = R11
.DEF T2 = R12
.DEF A = R16 ;R16:R31 CAN BE LOADED IMMEDIATE (LDI)
.DEF AH = R17
.DEF B = R18
.DEF C = R19
.DEF D = R20
.DEF I = R21
.DEF J = R22
.DEF K = R23
.DEF N = R24
;R26:R31 ARE 3x16 BIT POINTERS
.SET BLANK_CHAR=SPACE-LCD_TABLE
.ORG $0000
RJMP RESET
RESET: CLR ZERO
LDI A,3
MOV THREE,A
LDI A,HIGH(RAMEND) ;SETUP THE STACK POINTER
OUT SPH,A ;AT TOP OF MEMORY AND
LDI A,LOW(RAMEND) ;GROW DOWNWARDS
OUT SPL,A
RCALL LCD_INIT ;INITIALIZE LCD
RCALL LCD_CLR ;CLEAR LCD SEGMENTS
SAYHELLO:
LDI A,0
LOOP: PUSH A ;SAVE CONTENTS OF A
RCALL HELLO ;WAIT
RCALL DELAY
RCALL WORLD
RCALL DELAY ;WAIT
RCALL FROM
RCALL DELAY
RCALL AVR
RCALL DELAY
RCALL ASM
RCALL DELAY
RCALL LCD_CLR ;CLEAR LCD
RCALL DELAY ;WAIT
POP A ;RESTORE A
INC A
CPI A,255
BRNE LOOP
DONE: RJMP SAYHELLO
;---------------;
; HELLO & WORLD ;
;---------------;
HELLO: LDI ZL,LOW(HELLO_DAT*2)
LDI ZH,HIGH(HELLO_DAT*2)
RCALL SHOWBUF
RET
HELLO_DAT: .DB "HELLO "
WORLD: LDI ZL,LOW(WORLD_DAT*2)
LDI ZH,HIGH(WORLD_DAT*2)
RCALL SHOWBUF
RET
WORLD_DAT:.DB " WORLD"
FROM: LDI ZL,LOW(FROM_DAT*2)
LDI ZH,HIGH(FROM_DAT*2)
RCALL SHOWBUF
RET
FROM_DAT: .DB " FROM "
AVR: LDI ZL,LOW(AVR_DAT*2)
LDI ZH,HIGH(AVR_DAT*2)
RCALL SHOWBUF
RET
AVR_DAT: .DB " AVR "
ASM: LDI ZL,LOW(ASM_DAT*2)
LDI ZH,HIGH(ASM_DAT*2)
RCALL SHOWBUF
RET
ASM_DAT: .DB " ASM "
;-------------------------------;
; COPIES TEXT TO DISPLAY BUFFER ;
; MUST LOAD (Z) FIRST ;
;-------------------------------;
SHOWBUF:PUSH A
LPM A,Z+
MOV R7,A
LPM A,Z+
MOV R6,A
LPM A,Z+
MOV R5,A
LPM A,Z+
MOV R4,A
LPM A,Z+
MOV R3,A
LPM A,Z+
MOV R2,A
RCALL DISPN
POP A
RET
;-----------------------------------------------;
; DISPN - DISPLAY THE NUMBER IN R7:R2 REGISTERS ;
; NOTE CHR6BUF MUST BE POINTING 6 CHAR BUFFER ;
; APR/06 VERSION II WITH ASCII XLATION ;
;-----------------------------------------------;
DISPN: LDI XL,LOW(CHR6BUF) ;POINTS BUFFER-6
LDI XH,HIGH(CHR6BUF)
;-------------------------;
; ENTER HERE IF XH:XL SET ;
;-------------------------;
LCD_DSP: LDI N,6 ;SIX CHARS
LDI B,$F0 ;BITMASK
DSPNXT: LD A,X+ ;FETCH THE CHAR TO DISP
CPI A,' ' ;SPACE?
BRNE NOSPC ;SPACE XLATION
LDI A,BLANK_CHAR
NOSPC:
CPI A,97 ;CHARACTER XLATION
BRLO NOSMLET ;SMALL LETTERS?
SUBI A,$20 ;FOLD#1 a=>A
NOSMLET: CPI A,64 ;CAP LETTERS
BRLO NOBGLET ;
SUBI A,$37 ;FOLD#2 A=>10
NOBGLET: CPI A,47 ;ASCII NUMBERS
BRLO NOANUM ;
SUBI A,$30 ;FOLD#3 "0"=>0
NOANUM: LSL A ;POINT Z INTO TABLE
LDI ZL,LOW(LCD_TABLE*2)
LDI ZH,HIGH(LCD_TABLE*2)
ADD ZL,A ;OFFSET INTO
ADC ZH,ZERO ;CHARACTER TABLE
LDI YL,LOW(LCDDR1)-1 ;(=251)POINTS TO
CLR YH ;LCD SEGMENTS
MOV A,N ;USE COUNTER
DEC A
LSR A ;AS OFFSET TO
ADD YL,A ;SEGMENTS
SET
LDI I,4
DISPLUP: CPI YL,LOW(LCDDR8) ;PAST CHECK POINT?
BRLO NOZINC ;PAST 2ND READ?
BRTC NOZINC ;SHOULD WE INCZ?
ADIW ZH:ZL,1 ;INCZ AFTER 2ND READ
CLT ;STOP FURTHER INCZ
NOZINC: LPM A,Z ;LOAD SEGMENT DATA
SBRS I,0 ;USE BIT0
SWAP A ;SWAP ON EVEN SEGS
SBRC N,0 ;USE BIT0
SWAP A ;SWAP ON EVEN DIGITS
POTRIP: AND A,B ;MASK NEEDED INFO
COM B ;INVERT MASK
LD C,Y ;READ-IN SEGMENT
AND C,B ;CLEAR A SPOT
OR A,C ;SHOVE-IN NEW
ST Y,A ;WRITE-BACK
COM B ;RE-INVERT MASK
ADIW YH:YL,5 ;NEXT SEG
DEC I
BRNE DISPLUP ;DONE 4 SEGS?
SKPNUM: COM B ;INVERT BIT-MASK
DEC N ;DONE 6 DIGITS?
NOINC: BRNE DSPNXT
RET
;---------------------------;
; CLEAR ALL SEGMENTS ON LCD ;
;---------------------------;
LCD_CLR: LDI YL,LOW(LCDDR0)
CLR YH
CLRLUPE: ST Y+,ZERO
CPI YL,LCDDR18+1
BRNE CLRLUPE
RET
;-------------------------------;
; INITIALIZE LCD DISP REGISTERS ;
;-------------------------------;
LCD_INIT: PUSH A
LDI A,$B7 ;183 (1<<LCDCS) | (3<<LCDMUX0) | (7<<LCDPM0)
STS LCDCRB, A ;ENABLE ALL SEGEMENTS
LDI A,7 ;(0<<LCDPS0) | (7<<LCDCD0)
STS LCDFRR, A ;SET PRESCALER TO 32KHz
LDI A,$0E ;14 (1<<LCDCC3) | (1<<LCDCC2) | (1<<LCDCC1)
STS LCDCCR, A ;SET THE CONTRAST
LDI A,$C0 ;192(1<<LCDEN) | (1<<LCDAB)
STS LCDCRA, A ;ENABLE THE LCD
POP A
RET
;-----------------------------------;
; PAUSE/DELAY ROUTINE ;
; USES R0:R1 - NOT RESTORED ;
; WARNING R0:R1 ARE NOT INITIALIZED ;
; USES A - RESTORED ;
;-----------------------------------;
PAUSE:
DELAY: PUSH A
LDI A,32
DLUPE: DEC R0
BRNE DLUPE
DEC R1
BRNE DLUPE
DEC A
BRNE DLUPE
POP A
RET
;-----------------------------------------------------------;
; RETRO DAN'S IMPROVED LCD CHARACTER TABLE V1.2 ;
;-----------------------------------------------------------;
LCD_TABLE:
; --mpndlegcjfhbk--a <------> LCD SEGMENTS
.DW 0b0001010101010001 ;ZERO
;DW 0b0101010101011001 ;0/ -----a-----
.DW 0b0010000010000000 ;1 | \ | / |
;DW 0b0000000100011000 ;1 f h j k b
.DW 0b0001111000010001 ;2 | \ | / |
.DW 0b0001101100010001 ;3 --g-- --l--
.DW 0b0000101101010000 ;4 | / | \ |
.DW 0b0001101101000001 ;5 e p n m c
.DW 0b0001111101000001 ;6 | / | \ |
.DW 0b0000000101010001 ;7 -----d-----
.DW 0b0001111101010001 ;8
.DW 0b0001101101010001 ;9
.DW 0b0000111101010001 ;A
.DW 0b0011100110010001 ;B -----a-----
.DW 0b0001010001000001 ;C | \ | / |
.DW 0b0011000110010001 ;D f h j k b
.DW 0b0001111001000001 ;E | \ | / |
.DW 0b0000111001000001 ;F --g-- --l--
.DW 0b0001110101000001 ;G | / | \ |
.DW 0b0000111101010000 ;H e p n m c
.DW 0b0010000010000000 ;I | / | \ |
.DW 0b0001010100010000 ;J -----d-----
.DW 0b1000011001001000 ;K
.DW 0b0001010001000000 ;L
.DW 0b0000010101111000 ;M
.DW 0b1000010101110000 ;N
.DW 0b0001010101010001 ;0
.DW 0b0000111001010001 ;P
.DW 0b1001010101010001 ;Q
.DW 0b1000111001010001 ;R
.DW 0b0001101101000001 ;S -----a-----
;DW 0b1001000000100001 ;S | \ | / |
.DW 0b0010000010000001 ;T f h j k b
.DW 0b0001010101010000 ;U | \ | / |
.DW 0b1000000100110000 ;V --g-- --l--
.DW 0b1100010101010000 ;W | / | \ |
.DW 0b1100000000101000 ;X e p n m c
.DW 0b0010000000101000 ;Y | / | \ |
.DW 0b0101000000001001 ;Z -----d-----
.DW 0b0001010001000001 ;[
.DW 0b1000000000100000 ;\
.DW 0b0001000100010001 ;]
.DW 0b0000000001100000 ;^
.DW 0b0001000000000000 ;_
.DW 0b0000000000001000 ;'
.DW 0b1110101010101000 ;*
.DW 0b0010101010000000 ;+
SPACE:.DW 0 ;(SPACE) ;
.DW 0b0000101000000000 ;-
.DW 0b0100000000000000 ;.
.DW 0b0100000000001000 ;/
.DW 0b1000000000001000 ;<
.DW 0b0001101000000000 ;=
.DW 0b0100000000100000 ;>