Silent Q

Azog's little slice of the world. Whee.

New techniques

Posted By 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

Comments

Comments are closed.