;************************************************************** ;* This stationery serves as the framework for a * ;* user application. For a more comprehensive program that * ;* demonstrates the more advanced functionality of this * ;* processor, please see the demonstration applications * ;* located in the examples subdirectory of the * ;* Freescale CodeWarrior for the HC12 Program directory * ;************************************************************** ; Include derivative-specific definitions INCLUDE 'derivative.inc' ; export symbols XDEF Entry, _Startup, main ; we use export 'Entry' as symbol. This allows us to ; reference 'Entry' either in the linker .prm file ; or from C/C++ later on XREF __SEG_END_SSTACK ; symbol defined by the linker for the end of the stack ; variable/data section MY_EXTENDED_RAM: SECTION ; Insert here your data definition. OLDKEY rmb 1 ; variable to store the value of the last key pressed CNT1 rmb 1 ; counter LCDBUF: rmb 1 ; code section MyCode: SECTION main: jmp Entry _Startup: ;******* KEYPAD constants _KEY_TBL: FCC '123A456B789C*0#D' ; keypad keys table ;******* LCD constants WR: equ $20 ; LCD read/write control signal RS: equ $40 ; LCD register select signal EN: equ $80 ; LCD enable signal ;******** Program Entry Entry: LDS #__SEG_END_SSTACK ; initialize the stack pointer CLI jsr INITKEY ; initialize keyboard jsr DELAY50M jsr Init_LCD MainLoop: ldaa #$0F staa DDRG ; light up the EVB Leds KeySearch: jsr DELAY10M jsr GETKEY ; get the key from keypad, stored in A tsta ; see if a key was pressed beq KeySearch ; if nothing go to loop staa DDRG ; light up the first byte of the key on the leds jsr LCD_OUT ; write the character to the LCD jsr EE_TEST KeyPressed: jsr DELAY10M jsr GETKEY ldab OLDKEY cmpb #$00 ; check if keypad is released ; play DTMF bne KeyPressed ; if not loop back bra MainLoop ; restart. RTS ;---------------------------------------------------------------------------------------------------------- ; KEYPAD CONTROLLER CODE ;---------------------------------------------------------------------------------------------------------- ; DATA DEFINITIONS INITKEY: ldaa #$0F ; set Port H direction (0=input, 1=output) staa DDRH ; ldaa #$f0 ; clr DDRJ ; port J is input ldaa #$0F ; staa PPSJ ; set for pull downs ldaa #$0F staa PERJ ; enable pull downs rts GETKEY: jsr KEYSCAN rts KEYSCAN: movb #$0F,PTH ; set all keypad columns ldaa PTJ ; get keypad port anda #$0F ; keymask beq KEYRESET ; branch if no key pressed KEYSCAN1: ; determine wich key is pressed clr PTH ; clear all keypad columns clrb ; clear row counter movb #$01,PTH ; set column 1 KEYLP: jsr KEYDLY ; wait for lines to settle ldaa PTJ ; get keypad port anda #$0F ; mask row for data bne KEYSCAN2 ; branch if key is pressed lsl PTH ; set next column addb #$04 ; next row count cmpb #$10 ; check if counter == maxDigits bne KEYLP ; look for key KEYRESET: clr OLDKEY ; clear any oldkey KEYRST1: movb #$08,CNT1 ; set debounce time counter KEYRST2: movb #$0F,PTH ; set all keypads high clra ; clear key status rts KEYSCAN2: incb ; increment key number lsra ; shift row value to low nibble bcc KEYSCAN2 ; loop until key found cmpb OLDKEY ; test if same key bne KEYNEW ; if not, start new key dec CNT1 ; same key, debounce beq KEYSAVE ; if yes submit key bpl KEYRST2 ; if still in debounce wait inc CNT1 ; prep for next cycle bra KEYRST2 KEYNEW: stab OLDKEY ; save current key bra KEYRST1 ; stat debounce next time KEYSAVE: ldx #_KEY_TBL ; get start of key table decb ; 0 offset key number ldaa B,X ; load offset key in a rts KEYDLY: ldx #$100 ; clear offset count KEYDLY1: nop dex ; decrement counter bne KEYDLY1 ; loop if time not yet up rts ;---------------------------------------------------------------------------------------------------------- ; LCD CONTROLLER CODE ;---------------------------------------------------------------------------------------------------------- Init_LCD: jsr Init_Spi ; set up spi jsr LCD_INIT ; init lcd bset LCDBUF,RS ; set lcd to data input jsr LCD_SEND ; send to lcd rts LCD_INIT: bclr LCDBUF,RS+EN ; set LCD to receive instructions jsr LCD_SEND ; 4 bit initialization, according to manual jsr DELAY20M ; delay ldaa #$03 ; send 3 jsr LCD_WR_4 jsr DELAY05M ; wait 5 msec ldaa #$03 ; send 3 jsr LCD_WR_4 jsr DELAY1M ; wait 1 msec ldaa #$03 ; send 3 jsr LCD_WR_4 ldaa #$02 ; send 2 jsr LCD_WR_4 jsr DELAY1M ldaa #$24 ; 1 lines, 5X10 matrix character jsr LCD_CMD ; write command jsr DELAY1M ldaa #$0F ; display, cursor and blik on jsr LCD_CMD ; send command jsr DELAY1M ldaa #$06 ; cursor increment, shift off jsr LCD_CMD ; send command jsr DELAY1M ldaa #$01 ; reset and clear display jsr LCD_CMD jsr DELAY10M ldaa #$80 ; display ram address set jsr LCD_CMD jsr DELAY10M ; reset LCD states ldaa #$00 ; turn all signals off staa LCDBUF ; save states jsr LCD_SEND ; send signals rts Init_Spi: ; turn on SPI movb #$50,SPICR1 ; setup SPI ( enable and set to master mode ) movb #$04,SPIBR ; set up Spi baud clock rate (module clock divisor = 32) movb #$80,DDRS ; idle LCD select movb #$80,PTS ; set SPI SS to output bset LCDBUF,WR bclr LCDBUF,EN jsr LCD_SEND rts ;----------------------------------------- ; Simple Serial Driver (SPI), source code ;----------------------------------------- SS_IO: ldab SPISR ; clear status of SPI SS_IO_LP1: brclr SPISR,#$20,SS_IO_LP1 ; wait if transmit empty is not set staa SPIDR ; send/receive byte SS_IO_LP2: brclr SPISR,#$80,SS_IO_LP2 ; wait if interrupt flag is not set ldaa SPIDR ; read receive value rts ;--------------------------- ; LCD Routines ;--------------------------- LCD_SEND jsr DELAY10M ldaa LCDBUF ; load data & signals movb #$00, PTS ; select LCD jsr SS_IO ; send to LCD movb #$80, PTS ; idle LCD rts LCD_CMD: ; send a command to lcd bclr LCDBUF,RS ; select lcd command buffer jsr LCD_WR_8 ; wait rts LCD_OUT: ; write a byte bset LCDBUF,$10 ; select LCD data buffer jsr LCD_WR_8 ; write byte rts ; Lcd write 4 bit data, lower 4 bits of acc A ; bit assignment ; 0 = Lcd-Db4 4 = ; 1 = Lcd-Db5 5 = ; 2 = Lcd-Db6 6 = RS ; 3 = Lcd-Db7 7 = EN LCD_WR_4: psha ldaa LCDBUF ; load lcd buffer anda #$f0 ; get only control signals pulb ; get data andb #$0f ; only bits 0-3 are data aba staa LCDBUF ; save data & lcd signals bclr LCDBUF,EN ; clear EN signal jsr LCD_SEND ; send the data jsr DELAY1M bset LCDBUF,EN ; set EN signal jsr LCD_SEND ; send data jsr DELAY1M bclr LCDBUF,EN ; clear EN signal jsr LCD_SEND ; send data rts ; lcd write 8 bit data, lower 4 bits first in accA LCD_WR_8: psha ; save a lsra ; shift upper 4 bits to lower lsra lsra lsra jsr LCD_WR_4 ; write upper 4 bits to lcd pula jsr LCD_WR_4 ; write lower 4 bits to lcd rts ;----------------------- ; Delay routines ;----------------------- DELAY50M: bsr DELAY20M bsr DELAY20M bsr DELAY10M rts DELAY20M: bsr DELAY10M bsr DELAY10M rts DELAY10M: bsr DELAY05M bsr DELAY05M rts DELAY05M: pshx ldx #4998 jsr DELML01 pulx rts DELAY1M: pshx ldx #998 jsr DELML01 pulx rts DELML01: ; delay 1 usec nop nop nop nop dex bne DELML01 rts EE_TEST: psha ldaa #$80 ; make sure porte 7 = output staa PORTE staa DDRE ldaa #$06 ; send write enabled jsr EE_SEND ; send command movb #$80,PORTE ; end command ldaa #$02 ; send test byte write bsr EE_SEND ldaa #$02 ; send address bsr EE_SEND ldaa #$55 ; send data pattern pula bsr EE_SEND movb #$80,PORTE ; end command jsr DELAY10M jsr DELAY10M jsr DELAY10M EE_READ: ldaa #$03 ; read back the data bsr EE_SEND ldaa #$02 ; send address bsr EE_SEND clra ; get the byte bsr EE_SEND movb #$80,PORTE ; end command rts EE_SEND: clr PORTE ; enable eeprom select jsr SS_IO ; send itd rts end