Files
aqhomecontrol/avr/modules/lcd2/xpt2046/main.asm
2025-11-10 15:55:31 +01:00

407 lines
9.0 KiB
NASM

; ***************************************************************************
; copyright : (C) 2025 by Martin Preuss
; email : martin@libchipcard.de
;
; ***************************************************************************
; * This file is part of the project "AqHome". *
; * Please see toplevel file COPYING of that project for license details. *
; ***************************************************************************
#ifndef AQH_AVR_XPT2046_MAIN_ASM
#define AQH_AVR_XPT2046_MAIN_ASM
; ***************************************************************************
; defines
.equ XPT2046_SPIMODE = (0<<SPIHW_MODE_SPEED0_BIT) | \
(0<<SPIHW_MODE_SPEED1_BIT) | \
(1<<SPIHW_MODE_DOUBLESPEED_BIT) | \
(0<<SPIHW_MODE_DATAORDER_BIT) | \
(0<<SPIHW_MODE_CPOL_BIT) | \
(0<<SPIHW_MODE_CPHA_BIT)
.equ XPT2046_CMD_READ_X = 0xd1
.equ XPT2046_CMD_READ_Y = 0x91
.equ XPT2046_CMD_READ_Z1 = 0xb1
.equ XPT2046_CMD_READ_Z2 = 0xc1
.equ XPT2046_AVERAGE = 2
.equ XPT2046_Z_THRESHOLD = 50
.equ XPT2046_TIMER_VALUE = 3 ; every 300ms
.equ XPT2046_FLAGS_PRESSED_BIT = 7
.equ XPT2046_FLAGS_CHGCOORD_BIT = 6
.equ XPT2046_FLAGS_CHGPRESS_BIT = 5
; ***************************************************************************
; data
.dseg
xpt2046ValueBuffer: .byte (XPT2046_AVERAGE*2)
xpt2046CurrentX: .byte 2
xpt2046CurrentY: .byte 2
xpt2046CurrentZ: .byte 2
xpt2046Flags: .byte 1
xpt2046Timer: .byte 1
; ***************************************************************************
; code
.cseg
; ---------------------------------------------------------------------------
; @routine XPT2046_Init @global
XPT2046_Init:
clr r16
sts xpt2046CurrentX, r16
sts xpt2046CurrentX+1, r16
sts xpt2046CurrentY, r16
sts xpt2046CurrentY+1, r16
sts xpt2046CurrentZ, r16
sts xpt2046CurrentZ+1, r16
sts xpt2046Flags, r16
sts xpt2046Timer, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine XPT2046_Every100ms @global
XPT2046_Every100ms:
lds r16, xpt2046Timer
inc r16
cpi r16, XPT2046_TIMER_VALUE
brcs XPT2046_Every100ms_store
rcall xpt2046UpdateValues
clr r16
XPT2046_Every100ms_store:
sts xpt2046Timer, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine XPT2046_GetFlagsResetChg @global
;
; Return flags, clear stored flags XPT2046_FLAGS_CHGCOORD_BIT and
; XPT2046_FLAGS_CHGPRESS_BIT.
;
; @return r16 flags
; @clobbers r17
XPT2046_GetFlagsResetChg:
lds r16, xpt2046Flags
mov r17, r16
cbr r17, (1<<XPT2046_FLAGS_CHGCOORD_BIT) | (1<<XPT2046_FLAGS_CHGPRESS_BIT)
sts xpt2046Flags, r17
ret
; @end
; ---------------------------------------------------------------------------
; @routine xpt2046UpdateValues
xpt2046UpdateValues:
push r15
in r15, SREG
cli
lds r23, xpt2046Flags
rcall xpt2046BeginSpi ; (R16, R17)
; rcall xpt2046UpdateZ
ldi r16, XPT2046_CMD_READ_Z1
rcall xpt2046SendCommandRecv12Bit ; (R16)
sts xpt2046CurrentZ, r18
sts xpt2046CurrentZ+1, r19
ldi r16, LOW(XPT2046_Z_THRESHOLD)
ldi r17, HIGH(XPT2046_Z_THRESHOLD)
sub r18, r16
sbc r19, r17
brcc xpt2046UpdateValues_aboveThreshold
cbr r23, (1<<XPT2046_FLAGS_PRESSED_BIT) ; Z below threshold, not pressed
rjmp xpt2046UpdateValues_checkPressChg
xpt2046UpdateValues_aboveThreshold:
ori r23, (1<<XPT2046_FLAGS_PRESSED_BIT)
xpt2046UpdateValues_checkPressChg:
eor r16, r23
andi r16, (1<<XPT2046_FLAGS_PRESSED_BIT)
breq xpt2046UpdateValues_checkPress
ori r23, (1<<XPT2046_FLAGS_CHGPRESS_BIT)
xpt2046UpdateValues_checkPress:
mov r16, r23
andi r16, (1<<XPT2046_FLAGS_PRESSED_BIT) ; only read coords if pressed
breq xpt2046UpdateValues_storeFlags
rcall xpt2046UpdateX
rcall xpt2046UpdateY
xpt2046UpdateValues_storeFlags:
sts xpt2046Flags, r23
rcall xpt2046EndSpi ; (R16, R17)
out SREG, r15
pop r15
ret
; @end
; ---------------------------------------------------------------------------
; @routine xpt2046UpdateX
;
; @param r23 current xpt2046Flag (modified by routine)
; @clobbers (r16, r18, r19, r20, r21)
xpt2046UpdateX:
; dummy read
ldi r16, XPT2046_CMD_READ_X
rcall xpt2046SendCommandRecv12Bit ; (R16)
ldi r16, XPT2046_CMD_READ_X
rcall xpt2046ReadAvgValues ; (r16, r18, r19, r20, r21)
rcall xpt2046AverageValues ; (r16, r17, r21)
lds r16, xpt2046CurrentX
lds r17, xpt2046CurrentX+1
sts xpt2046CurrentX, r18
sts xpt2046CurrentX+1, r19
sub r16, r18
sbc r17, r19
breq xpt2046UpdateX_ret
ori r23, (1<<XPT2046_FLAGS_CHGCOORD_BIT)
xpt2046UpdateX_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine xpt2046UpdateY
;
; @param r23 current xpt2046Flag (modified by routine)
; @clobbers (r16, r18, r19, r20, r21)
xpt2046UpdateY:
; read Y
ldi r16, XPT2046_CMD_READ_Y
rcall xpt2046ReadAvgValues ; (r16, r18, r19, r20, r21)
rcall xpt2046AverageValues ; (r16, r17, r21)
lds r16, xpt2046CurrentY
lds r17, xpt2046CurrentY+1
sts xpt2046CurrentY, r18
sts xpt2046CurrentY+1, r19
sub r16, r18
sbc r17, r19
breq xpt2046UpdateY_ret
ori r23, (1<<XPT2046_FLAGS_CHGCOORD_BIT)
xpt2046UpdateY_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine xpt2046UpdateZ
;
; @param r23 current xpt2046Flag (modified by routine)
; @clobbers (r16, r18, r19, r20, r21)
xpt2046UpdateZ:
ldi r16, XPT2046_CMD_READ_Z1
rcall xpt2046SendCommandRecv12Bit ; (R16)
sts xpt2046CurrentZ, r18
sts xpt2046CurrentZ+1, r19
ldi r16, LOW(XPT2046_Z_THRESHOLD)
ldi r17, HIGH(XPT2046_Z_THRESHOLD)
sub r18, r16
sbc r19, r17
mov r16, r23
brcs xpt2046UpdateZ_overThreshold
cbr r23, (1<<XPT2046_FLAGS_PRESSED_BIT) ; Z below threshold, not pressed
rjmp xpt2046UpdateZ_checkPressChg
xpt2046UpdateZ_overThreshold:
ori r23, (1<<XPT2046_FLAGS_PRESSED_BIT)
xpt2046UpdateZ_checkPressChg:
eor r16, r23
andi r16, (1<<XPT2046_FLAGS_PRESSED_BIT)
breq xpt2046UpdateZ_ret
ori r23, (1<<XPT2046_FLAGS_CHGPRESS_BIT)
xpt2046UpdateZ_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine xpt2046AverageValues
;
; @return r19:r18 averaged value
; @clobbers r16, r17, r21
xpt2046AverageValues:
ldi xl, LOW(xpt2046ValueBuffer)
ldi xh, HIGH(xpt2046ValueBuffer)
ldi r21, XPT2046_AVERAGE
clr r18
clr r19
xpt2046AverageValues_loop:
ld r16, X+
ld r17, X+
add r18, r16
adc r19, r17
dec r21
brne xpt2046AverageValues_loop
.if (XPT2046_AVERAGE == 2)
lsr r19
ror r18
.elif (XPT2046_AVERAGE == 4)
lsr r19
ror r18
lsr r19
ror r18
.else
.error "XPT2046_AVERAGE is not 4"
.endif
ret
; @end
; ---------------------------------------------------------------------------
; @routine xpt2046ReadAvgValues
;
; @param r16 command
; @clobbers r16, r18, r19, r20, r21
xpt2046ReadAvgValues:
ldi xl, LOW(xpt2046ValueBuffer)
ldi xh, HIGH(xpt2046ValueBuffer)
mov r20, r16
ldi r21, XPT2046_AVERAGE
xpt2046ReadAvgValues_loop:
mov r16, r20
rcall xpt2046SendCommandRecv12Bit ; (R16)
st X+, r18
st X+, r19
dec r21
brne xpt2046ReadAvgValues_loop
ret
; @end
; ---------------------------------------------------------------------------
; @routine xpt2046BeginSpi
;
; @clobbers r16, r17
xpt2046BeginSpi:
ldi r16, XPT2046_SPIMODE
ldi r17, XPT2046_DEVICENUM
rjmp SPIHW_MasterStart ; (R17)
; @end
; ---------------------------------------------------------------------------
; @routine xpt2046EndSpi
;
; @clobbers r16
xpt2046EndSpi:
rjmp SPIHW_MasterStop ; (R16)
; @end
; ---------------------------------------------------------------------------
; @routine xpt2046SendCommandRecv12Bit
;
; @param r16 command
; @return r19:18 data
; @clobbers r16
xpt2046SendCommandRecv12Bit:
rcall xpt2046SendCommandRecv16Bit
lsr r19 ; >>1
ror r18
lsr r19 ; >>2
ror r18
lsr r19 ; >>3
ror r18
lsr r19 ; >>4
ror r18
ret
; @end
; ---------------------------------------------------------------------------
; @routine xpt2046SendCommandRecv16Bit
;
; @param r16 command
; @return r19:18 data
; @clobbers r16
xpt2046SendCommandRecv16Bit:
cbi SPIHW_SS_OUTPUT, SPIHW_SS_PIN ; SS low
rcall SPIHW_MasterTransfer ; (R16)
clr r16
rcall SPIHW_MasterTransfer ; (R16)
mov r19, r16
clr r16
rcall SPIHW_MasterTransfer ; (R16)
mov r18, r16
sbi SPIHW_SS_OUTPUT, SPIHW_SS_PIN ; SS high
ret
; @end
; ---------------------------------------------------------------------------
; @routine xpt2046SendCommandRecv8Bit
;
; @param r16 command
; @return r16 data
; @clobbers r16
xpt2046SendCommandRecv8Bit:
cbi SPIHW_SS_OUTPUT, SPIHW_SS_PIN ; SS low
rcall SPIHW_MasterTransfer ; (R16)
mov r18, r16
sbi SPIHW_SS_OUTPUT, SPIHW_SS_PIN ; SS high
ret
; @end
#endif ; AQH_AVR_XPT2046_MAIN_ASM