| CODE |
;---------------------------------------------------; ; H E L L O W O R L D B Y R E T R O D A N ; ; ============================================= ; ; ; ; BUTTERFLY EQUIVALENT OF the "HELLO WORLD" PROGRAM; ; CREATED: 01-MAR-06 LAST UPDATE: 28-MAR-06; ;---------------------------------------------------; .INCLUDE "M169DEF.INC" ;BUTTERFLY/ATMEGA169 DEFS ;---------------------------------: ; RENAME/DEFINE WORKING REGISTERS; ;---------------------------------; .DEF ZERO = R10 ;DEFINE REGISTERS .DEF A = R16 ;---------------------------------------; ; START OF FLASH MEMORY / RESTART POINT; ;---------------------------------------; .ORG $0000 RJMP START ;RESET POINT ;-----------------------------------------; ; START OF MAIN PROGRAM / INITIALIZATIONS; ;-----------------------------------------; START: LDI A,HIGH(RAMEND) ;SETUP THE STACK POINTER OUT SPH,A ;AT TOP OF MEMORY AND LDI A,LOW(RAMEND) ;LET STACK GROW DOWNWARDS OUT SPL,A CLR ZERO ;MAKE SURE ZERO = 0 RCALL LCD_INIT ;INITIALIZE DISPLAY ;--------------------------------------------------; ; DESCRIPTION LCD SEGEMENTS: ----a---- ; ; NYBBLE1 NYBBLE2 |\ | /| ; ; LCDDRn ....... k - - a k - - a f h j k b ; ; LCDDRn+5 ..... j f h b j f h b | \ | / | ; ; LCDDRn+10 .... l e g c l e g c -g-- --l-- ; ; LCDDRn+15 .... m p n d m p n d | /|\ | ; ; e p n m c ; ; Small letters in NYBBLES =======> |/ | \ | ; ; Refer to this segment map ----d---- ; ; ; ; TWO CHARS STUFFED IN A BYTE, AND THEY'RE SPREAD ; ; ACROSS FOUR REGISTERS THAT ARE FIVE BYTES APART ; ; I USE 'BRUTE-FORCE' TO SWITCH SEGMENTS ON/OFF. ; ;--------------------------------------------------; MAIN_LOOP: LDI A,0b00010000 ;SETUP 1ST TWO CHARS 'HE' STS LCDDR0,A ;'E' IN LOW NYBBLE LDI A,0b01000101 ;'H' IN HIGH NYBBLE STS LCDDR5,A ;LCD REGS SKIP BY FIVE LDI A,0b11101111 ;FOR EACH SCANLINE STS LCDDR10,A LDI A,0b00010000 STS LCDDR15,A LDI A,0b01000100 ;DISPLAY 'LL' STS LCDDR6,A LDI A,0b01000100 STS LCDDR11,A LDI A,0b00010001 STS LCDDR16,A LDI A,0b00000001 ;DISPLAY '0' STS LCDDR2,A LDI A,0b00000101 STS LCDDR7,A LDI A,0b00000101 STS LCDDR12,A LDI A,0b00000001 STS LCDDR17,A RCALL WCLR ; LETS DO IT AGAIN FOR THE WORD: "WORLD" LDI A,0x10 ;DISPLAY 'WO' STS LCDDR0,A LDI A,0x55 STS LCDDR5,A LDI A,0x55 STS LCDDR10,A LDI A,0x1C STS LCDDR15,A LDI A,0x01 ;DISPLAY 'RL' STS LCDDR1,A LDI A,0x45 STS LCDDR6,A LDI A,0x4E STS LCDDR11,A LDI A,0x18 STS LCDDR16,A LDI A,0x01 ;DISPLAY 'D' STS LCDDR2,A LDI A,0x09 STS LCDDR7,A LDI A,0x01 STS LCDDR12,A LDI A,0x03 STS LCDDR17,A RCALL WCLR RJMP MAIN_LOOP ;------------------------------------; ; WAITS, CLEARS DISPLAY, WAITS AGAIN; ;------------------------------------; WCLR: RCALL DELAY ;WAIT RCALL LCD_CLR ;CLEAR SCREEN RCALL DELAY ;WAIT RET ;-------------------------------------; ; CLEAR LCD SEGMENTS BY WRITING ZEROS; ;-------------------------------------; LCD_CLR: LDI XL,LOW(LCDDR0) LDI XH,HIGH(LCDDR0) CLUPE: ST X+,ZERO CPI XL,LCDDR18+1 BRNE CLUPE RET ;----------------------------------; ; INITIALIZE LCD DISPLAY REGISTERS; ;----------------------------------; LCD_INIT: ;--------------------------------------------------------; ; LCDCRB: LCD CONTROL REGISTER 'B' ; ; BITS-0/1/2: LCDPMn PORT MASK: nnn PORT MAX SEGS ; ; 000 SEGO:12 13 SEGMENTS; 001 SEGO:14 15 SEGMENTS; ; 010 SEGO:16 17 SEGMENTS; 011 SEGO:18 19 SEGMENTS; ; 100 SEGO:20 21 SEGMENTS; 101 SEGO:22 23 SEGMENTS; ; 110 SEGO:23 24 SEGMENTS; 111 SEGO:24 25 SEGMENTS; ; ; ; BIT-3: (READS ZERO) ; ; ; ; BITS-4/5: LCDMUXn: 00=STATIC, 01=1/2 10=1/3 11=1/4 ; ; BIT-6: LCD2B, 1/2 BIAS: 1=1/2 BIAS, 0=1/3 BIAS ; ; BIT-7: LCDCS, CLOCK SELECT: 0=INTERNAL, 1=EXTERNAL ; ;--------------------------------------------------------; ;SET CLOCK TO EXTERNAL, 1/4 DUTY CYCLE, 25 SEGMENTS LDI A,0b10110111;(1<<LCDCS)|(3<<LCDMUX0)|(7<<LCDPM0)=$B7 STS LCDCRB, A ;[LCDCS,LCD2B,LCDMUX1,+MUX0,-,LCDPM2,+PM1,+PM0] ;--------------------------------------------------------; ; LCDFFR: ; ; BIT-7: (READS ZERO) ; ; BITS-4/5/6: LCDPSn: PRESCALE ; ; 000=/16 001=/64 010=/128 011=/256 ; ; 100=/512 101=/1024 110=/2048 111=/4096 ; ; ; ; BIT-3: (READS ZERO) ; ; ; ; BITS-0/1/2: LCD CLOCK DIVIDE ; ; 001=/2, 010=/3 011=/4 100=/5 101=/6 110=/7 111=/8 ; ; FREQ=LCD_CLOCK/[D*N*K] ; ; D=(THE ABOVE DIVISION FACTOR) ; ; N=PRESCALE OF 16/64/128/256/512/1024/2048/4096 ; ; K=DUTY CLYCLE: STATIC, 1/2 OR 1/4 ; ;--------------------------------------------------------; ;SET PRESCALE TO /16, CLOCK DIVIDE TO /8 LDI A,0b00000111;(0<<LCDPS0)|(7<<LCDCD0)=$7 STS LCDFRR, A ;[-,LCDPS2,+PS1,+PS0,-,LCDCD2,+CD1,+CD0] ;----------------------------------------------------------; ; LCDCCR: ; ; BITS-5/6/7: DISPLAY DRIVE TIME ; ; 000=330uS 001= 70 010= 150 011=450 ; ; 100=575uS 101=850 110=1150 111=(50% OF CLOCK) ; ; BIT-4: MAX DRIVE 1=100% DRIVE ALL TIME IGNORE ABOVE ; ; ; ; BITS-0/1/2/3: CONTRAST VOLTS INCREMENTS OF +0.05 ; ; 0000=2.6V 0001=2.65 0010=2.7V ... 1110=3.3V 1111=3.35V ; ;----------------------------------------------------------; ;SET DRIVE TIME OT 330uS, CONTRAST TO 3.30 VOLTS LDI A,0b00001110;(1<<LCDCC3)|(1<<LCDCC2)|(1<<LCDCC1)=$0E STS LCDCCR, A ;[LCDDC2,+DC1,+DC0,LCDMDT,LCDCC3,+CC2,+CC1,+CC0] ;---------------------------------------------------------; ; LCDCRA: LCD CONTROL REGISTER 'A' ; ; BIT-0: LCDBL, LCD BLANKING: 1=BLANKED AFTER EACH FRAME; ; BIT-1: LCDCCD, CONTRAST CONTROL: 1=DISABLED ; ; BIT-2: LCDBD, BUFFER DISABLE: 1=DISABLED (LOW POWER) ; ; BIT-3: LCDIE, INTERUPT ENABLE: 1=ENABLED ; ; BIT-4: LCDIF, INTERUPT FLAG: CONTROLLED BY HW ; ; BIT-5: (READS ZERO) ; ; BIT-6: LCDAB, LOW POWER: 1=LOW_POWER, 0=NORMAL ; ; BIT-7: LCDEN, LCD ENABLE: 1=0N ; ;---------------------------------------------------------; ;ENABLE THE LCD LOW POWER MODE NO BLANKING CONTRAST CONTROL ON LDI A,0b11000000;(1<<LCDEN)|(1<<LCDAB)=$C0 STS LCDCRA,A ;[LCDEN,LCDAB,-,LCDIF,LCDIE,LCDBD,LCDCCD,LCDBL] RET ;--------------------; ; MY CASCADING DELAY; ;--------------------; DELAY: LDI A,8 DLUPE: DEC R0 BRNE DLUPE DEC R1 BRNE DLUPE DEC A BRNE DLUPE RET |