Posted By azog on October 25, 2005
This snippet is what I learned trying various new things:
#1 – the hardest part was using the LCD. The LCD is broken down in a strange arrangement of rows and columns which is/was hard for me to wrap my head around. I am still not sure I fully comprehend this. For now, I need a sheet of paper with the matrix, and a blank sheet of paper drawing out the bits.
#2 – setting up the stack pointer. Previous tests were basically “top-down”, with interrupts. Now, I want to clear the LCD, and display some words on the LCD, so I figured subroutines were the best. Using calls and rets I needed to properly define the stack, otherwise the device would hit the reset vector on return.
So this just adds some “functionality” which displays the status of the LED on the LCD. When the LED is lit, the LCD displays “ON”; and when the LED is not lit, the LCD displays OFF. But in different areas of the screen. Whee.
Oh, I also like to use binary for some of the bytes, especially those which are bit-driven, like the LCD segments. It helps to visualize what’s happening.
.include "m169def.inc" ; hardware reset .org 0x0000 jmp RESET ; interrupt for timer 1 output compare mode A .org 0x00e0 jmp CLKINT RESET: ; set up the stack pointer ldi R16,high(RAMEND) out SPH,R16 ldi R16,low(RAMEND) out SPL,R16 ; enable the LCD ldi R16,0x80 sts LCDCRA,R16 ldi R16,0xB7 sts LCDCRB,R16 ldi R16,0x10 sts LCDFRR,R16 ldi R16,0x0fF sts LCDCCR,r16 ; initial clear the LCD, Just In Case call CLRLCD ;define a seed value for flipping bits ldi R21,0xFF ;set PB-1 as output ldi R16,0x01 out DDRB,R16 ;high-byte of compare value ldi R16,0xFF sts OCR1AH,R16 ;low byte of compare value ldi R16,0xFF sts OCR1AL,R16 ;high byte of starting clock value ldi R16,0x00 sts TCNT1H,R16 ;low byte of starting clock value ldi R16,0x01 sts TCNT1L,R16 ;enable timer1 with prescaler 1 and 0 ldi R16,0b00000011 sts TCCR1B,R16 ;enable output compare A ldi R16,0x02 sts TIMSK1,R16 ;enable interrupts sei LOOP: ; idlly wait for an intterupt jmp LOOP CLKINT: ; probably unnecessary call CLRLCD ; exclusive-or the compare register with 0xFF ; for a comparison. each interrupt cycle will ; "toggle" R20 off or on, which will be used to ; determine the state of the LED eor R20,R21 ; if the registers match, i.e., the state is ON, ; then go to this routine cp R20,R21 breq OFFSET ; otherwise enable (turn on) the LED, ; set the LCD display to the appropriate state ; and return from interrupt ldi R16,0x01 out PORTB,R16 call DISPON reti OFFSET: ; jump here if the registers match ; turn off the LED, set the LCD and return from interrupt ldi R16,0x00 out PORTB,R16 call DISPOFF reti CLRLCD: ; blank all LCD segments ; R4, R9 and R14 do not exist ldi r22,0x00 sts LCDDR0,r22 sts LCDDR1,r22 sts LCDDR2,r22 sts LCDDR3,r22 ; sts LCDDR4,r22 sts LCDDR5,r22 sts LCDDR6,r22 sts LCDDR7,r22 sts LCDDR8,r22 ; sts LCDDR9,r22 sts LCDDR10,r22 sts LCDDR11,r22 sts LCDDR12,r22 sts LCDDR13,r22 ; sts LCDDR14,r22 sts LCDDR15,r22 sts LCDDR16,r22 sts LCDDR17,r22 sts LCDDR18,r22 ret DISPOFF: ; clear the LCD ; call CLRLCD ; load the word "OFF" into the proper nybbles ldi R16,0b00010001 sts LCDDR0,R16 ldi R16,0b01000101 sts LCDDR5,R16 ldi R16,0b01100101 sts LCDDR10,R16 ldi R16,0b00000001 sts LCDDR15,R16 ldi R16,0b00000001 sts LCDDR1,R16 ldi R16,0b00000100 sts LCDDR6,R16 ldi R16,0b00000110 sts LCDDR11,R16 ldi R16,0b00000000 sts LCDDR16,R16 ret DISPON: ;clear the LCD ; call CLRLCD ;load the word "ON" into their proper segments ldi R16,0b00000001 sts LCDDR2,R16 ldi R16,0b01110101 sts LCDDR7,R16 ldi R16,0b01010101 sts LCDDR12,R16 ldi R16,0b10000001 sts LCDDR17,R16 ret