📄 bbu_codec.s
字号:
stmfd sp!, {r1-r7,lr} ; Save used registers
bl BBU_TSI_LIFT ; Get user command from touch screen
mov r5, r1 ; Copy Y data to r5
;
; When the code gets here, it means the user has touched the LCD and
; lifted the pen (or stylus, or finger). Now the code will figure out
; if the last point touched falls within a previously defined box that
; was drawn on the LCD using the BBU_LCD_TBOX subroutine.
;
; The first step is convert the touch panel data into pixel location
; data based on the current configuraqtion of the LCD. For the Littleton
; the ideal touch panel data would come back as follows:
;
; FF,00 +---------+ 00,00 (X,Y)
; | |
; | |
; | | X,Y data in hex format
; | | X data is in r4 (0-255)
; | LCD | Y data is in r5 (0-255)
; | |
; | |
; | |
; | |
; FF,FF +---------+ 00,FF
;
; BBU "flips" the X data so 00 is on the left and FF is on the right.
;
; BBU uses the touch panel calibration data to provide more accurate
; feedback on the location the user touched on the panel. the general
; formula used is:
;
; pos = PW * (upos-LL) / (UL - LL)
;
; Or, The position (pos) in pixels = the pixel width times the reported
; user position (upos) minus the lower calibration limit (LL), all divided
; by the upper calibration limit (UL) minus the lower limit (LL).
;
mov r2, #0xFF ; Prepare to flip the X data
sub r4, r2, r0 ; Flip the X data and place in r4
ldr r2, =BBU_LCD_TYPE ; Address where LCD type is kept
ldrb r3, [r2] ; Get the LCD type
ands r3, r3, #0x01 ; Is it in VGA mode?
movne r1, #240 ; No - QVGA X multiplier
movne r2, #320 ; No - QVGA Y multiplier
moveq r1, #480 ; Yes - VGA X multiplier
moveq r2, #620 ; Yes - VGA Y multiplier
;
; Calculate X position
;
ldr r6, =BBU_TCAL_DATA ; Location of calibration data
ldr r3, [r6] ; Fetch X min/max values
mov r7, r3, LSR #16 ; Load X min value into r7
sub r4, r4, r7 ; r4 = upos - LL for X position
mul r0, r4, r1 ; r4 = X pixel location before division
and r3, r3, #0xFF ; Mask out max X calibration data
subs r1, r3, r7 ; r1 = UL - LL
;
; Ready to divide, but first we need to use the Y pixel width data in r2
; to free up this register for the divide routine.
;
ldr r4, [r6, #4] ; Fetch Y min/max values
mov r6, r4, LSR #16 ; Load Y min value into r6
sub r5, r5, r6 ; r5 = upos - LL for Y position
mul r5, r5, r2 ; r5 = Y pixel location before division
bl BBU_U32Divide ; Divide to get the X pixel location in r2
mov r0, r5 ; Move Y data into r0 for division
and r4, r4, #0xFF ; get Y max value in r4
sub r1, r4, r6 ; Generate divisor for Y position in r1
mov r4, r2 ; Save calculated X pixel position in r4
bl BBU_U32Divide ; Divide to get the Y pixel location in r2
mov r5, r2 ; Save this result in r5
;
; r4 now equals the estimated X location of the pixel
; r5 now equals the estimated Y location of the pixel
;
; Now the code looks at the touch box data to see if this location can
; be matched up with a box. The r4/r5 data must be greater than the
; location of the upper left corner of the box AND less then the location
; of the lower right corner of the box in order to get a match.
;
ldr r1, =TBOX_ARR ; Touch Box data array
ldr r0, =0xFFFF ; End of array marker
mov r6, #0 ; Set box number to zero
476 ldr r2, [r1, #4] ; Get lower right data
cmp r2, r0 ; End of array?
moveq r0, #0xFF ; Yes - no match found
beq %F479 ; ...and exit
cmp r2, #0 ; Is this data = zero
bne %F478 ; No - skip to compare code
add r1, r1, #8 ; Yes - point to next array entry
b %B476 ; And get another entry
;
; Non-zero table entry found - Do the compare on the upper left corner
;
478 ldr r2, [r1], #4 ; Fetch upper left corner data
and r3, r2, r0 ; Extract the Y data into r3
cmp r3, r5 ; Is the user pixel "below" this value?
addgt r1, r1, #4 ; No - point to next array entry
addgt r6, r6, #1 ; Increment box counter
bgt %B476 ; ...and get next array entry
mov r3, r2, LSR #16 ; r2 = X location of upper left corner
cmp r3, r4 ; Is the user pixel to the right?
addgt r1, r1, #4 ; No - point to next array entry
addgt r6, r6, #1 ; Increment box counter
bgt %B476 ; ...and get next array entry
;
; If the code got here the user pixel is below and to the right of the
; top left corner of this box. Test to see if it's above and to the left
; of the bottom right corner.
;
ldr r3, [r1], #4 ; Fetch the lower right corner data
add r2, r2, r3 ; Calculate pixel location of LR corner
and r3, r2, r0 ; Extract the Y data into r3
cmp r3, r5 ; Compare to the user Y pixel data
addlt r6, r6, #1 ; Not valid - increment box counter
blt %B476 ; ...and get next box entry
mov r2, r2, LSR #16 ; r2 = X location of lower right corner
cmp r2, r4 ; Is the user pixel to the left?
addlt r6, r6, #1 ; No - increment box counter
blt %B476 ; ...and get next box entry
;
; We have a match - return box count to the caller in r0
;
mov r0, r6
479 ldmfd sp!, {r1-r7,pc} ; Return to caller
ENDFUNC
;
;*******************************************************************************
;
; ******************
; * *
; * BBU_CODEC_TCAL * Subroutine
; * *
; ******************
;
; This subroutine is used to calibrate the touch panel on the LCD
;
; PARAMETER PASSING:
;
; INPUT:
;
; None
;
; OUTPUT:
;
; none (However, the touch screen calibration data is updated)
;
BBU_CODEC_TCAL FUNCTION
stmfd sp!, {r0-r6,lr} ; Save used registers
ldr r0, =BBU_TCAL_UD1 ; User directions
bl BBU_putstr ; Output to the user
mov r0, #0x7E0 ; Set the LCD background color to GREEN
bl BBU_LCD_COLOR ; Update the LCD
mov r0, #15 ; Row 15
mov r1, #2 ; Column 6
ldr r2 , =BBU_TCAL_MSG ; Message to LCD
bl BBU_LCD_put16x20str ; Send to LCD
ldr r4, =BBU_TCAL_DATA ; Calibration data saved here
;
; Display upper left calibration point
;
mov r0, #0 ; Row 0
mov r1, #0 ; Column 0
ldr r2 , =BBU_TCAL_PLUS ; Message to LCD
bl BBU_LCD_put16x20str ; Send to LCD
bl BBU_TSI_LIFT ; Get user command from touch screen
;
; Save upper left calibation data
;
mov r0, r0, LSL #16 ; Move X data 16 bits to the left
orr r0, r0, r1 ; Load Y data into the bottom 16 bits
str r0, [r4], #4 ; Save data & increment pointer
;
; Display upper right calibration point
;
mov r0, #0 ; Row 0
mov r1, #0 ; Column 0
ldr r2 , =BBU_TCAL_BLANK ; Message to LCD
bl BBU_LCD_put16x20str ; Send to LCD
mov r0, #0 ; Row 0
mov r1, #29 ; Column 29
ldr r2 , =BBU_TCAL_PLUS ; Message to LCD
bl BBU_LCD_put16x20str ; Send to LCD
bl BBU_TSI_LIFT ; Get user command from touch screen
;
; Save upper right calibation data
;
mov r0, r0, LSL #16 ; Move X data 16 bits to the left
orr r0, r0, r1 ; Load Y data into the bottom 16 bits
str r0, [r4], #4 ; Save data & increment pointer
;
; Display lower left calibration point
;
mov r0, #0 ; Row 0
mov r1, #29 ; Column 29
ldr r2 , =BBU_TCAL_BLANK ; Message to LCD
bl BBU_LCD_put16x20str ; Send to LCD
mov r0, #31 ; Row 31
mov r1, #0 ; Column 0
ldr r2 , =BBU_TCAL_PLUS ; Message to LCD
bl BBU_LCD_put16x20str ; Send to LCD
bl BBU_TSI_LIFT ; Get user command from touch screen
;
; Save lower left calibation data
;
mov r0, r0, LSL #16 ; Move X data 16 bits to the left
orr r0, r0, r1 ; Load Y data into the bottom 16 bits
str r0, [r4], #4 ; Save data & increment pointer
;
; Display lower right calibration point
;
mov r0, #31 ; Row 31
mov r1, #0 ; Column 0
ldr r2 , =BBU_TCAL_BLANK ; Message to LCD
bl BBU_LCD_put16x20str ; Send to LCD
mov r0, #31 ; Row 31
mov r1, #29 ; Column 29
ldr r2 , =BBU_TCAL_PLUS ; Message to LCD
bl BBU_LCD_put16x20str ; Send to LCD
bl BBU_TSI_LIFT ; Get user command from touch screen
;
; Save lower right calibation data
;
mov r0, r0, LSL #16 ; Move X data 16 bits to the left
orr r0, r0, r1 ; Load Y data into the bottom 16 bits
str r0, [r4] ; Save data
;
; Inform user the calibration is done
;
mov r0, #31 ; Row 31
mov r1, #29 ; Column 29
ldr r2 , =BBU_TCAL_BLANK ; Message to LCD
bl BBU_LCD_put16x20str ; Send to LCD
mov r0, #15 ; Row 15
mov r1, #2 ; Column 6
ldr r2 , =BBU_TCAL_DONE ; Message to LCD
bl BBU_LCD_put16x20str ; Send to LCD
;
; At this point there are 4 pairs of X,Y data in the data array. BBU will
; compute the average values of the max/min X, Y values by averaging the
; max and min X Y values and reload the array with this data so the the
; min/max value for the X value is in the first doubleword and the min/max
; value for the Y value is in the second doubleword. the data is currently
; arranged in the array as follows:
;
; bits: 31:16 15:0
; +--------+--------+
; Upper Left (UL) | X data | Y Data | BBU_TCAL_DATA + 0x0
; +--------+--------+
; Upper Right(UR) | X data | Y Data | BBU_TCAL_DATA + 0x4
; +--------+--------+
; Lower Left (LL) | X data | Y Data | BBU_TCAL_DATA + 0x8
; +--------+--------+
; Lower Right(LR) | X data | Y Data | BBU_TCAL_DATA + 0xC
; +--------+--------+
;
ldr r4, =BBU_TCAL_DATA ; Calibration data saved here
ldr r0, [r4, #0x4] ; Fetch UR data
ldr r1, [r4, #0xC] ; Fetch LR data
add r0, r0, r1 ; Add the min X values in bits 31:16
mov r0, r0, LSR #1 ; divide by 2
and r0, r0, #0xFF0000 ; Mask out all other data
ldr r1, [r4, #0x0] ; Fetch UL data
ldr r2, [r4, #0x8] ; Fetch LL data
add r1, r1, r2 ; Add the max X values in bits 31:16
mov r1, r1, LSR #17 ; divide by 2 & shift to bits 15:0
and r1, r1, #0xFF ; Mask out all other data
orr r0, r0, r1 ; r0 = average min/max X data
ldr r1, [r4, #0x0] ; Fetch UL data
ldr r2, [r4, #0x4] ; Fetch UR data
add r1, r1, r2 ; Add the min Y values in bits 15:0
mov r1, r1, LSR #1 ; divide by 2
and r1, r1, #0xFF ; Mask out all other data
mov r1, r1, LSL #16 ; Move min value to bits 31:16
ldr r2, [r4, #0x8] ; Fetch LL data
ldr r3, [r4, #0xC] ; Fetch LR data
add r2, r2, r3 ; Add the max Y values in bits 15:0
mov r2, r2, LSR #1 ; Divide by 2
and r2, r2, #0xFF ; Mask out unwanted data
orr r1, r1, r2 ; R1 = average min/max Y data
str r0, [r4] ; Save ave min/max X value
str r1, [r4, #4] ; Save ave min/max Y value
;
; The array now contains the following data:
;
; bits: 31:16 15:0
; +--------+--------+
; Average X data | X min | X max | BBU_TCAL_DATA + 0x0 (updated)
; +--------+--------+
; Average Y data | Y min | Y max | BBU_TCAL_DATA + 0x4 (updated)
; +--------+--------+
; Lower Left (LL) | X data | Y Data | BBU_TCAL_DATA + 0x8 (unchanged)
; +--------+--------+
; Lower Right(LR) | X data | Y Data | BBU_TCAL_DATA + 0xC (unchanged)
; +--------+--------+
;
; The average X, Y data will be used to estimate the point on the LCD that
; was touched. The lower left/right data (above) is simply ingnored.
;
499 ldmfd sp!, {r0-r6,pc} ; Return to caller
;
; TCAL Messages
;
BBU_TCAL_UD1 DCB 0xD,0xA," TOUCH PANEL CALIBRATION",0xD,0xA,0xA
DCB " Touch each of the four plus signs (+) as they appear",0xD,0xA
DCB " on the LCD to accuratly calibrate the touch panel to",0xD,0xA
DCB " the LCD screen.",0xD,0xA,0xA,0
BBU_TCAL_PLUS DCB "+",0
BBU_TCAL_BLANK DCB " ",0
BBU_TCAL_MSG DCB "Touch the + in each corner.",0
BBU_TCAL_DONE DCB " Calibration done! ",0
ALIGN 4
;
; Touch panel calibration data below is the raw X,Y data from the four
; corners of the touch panel. For all practical purposes, these values can
; be assumed to be in the extreme corners of the display (the difference
; between touching the center of the + in each corner and the LCD active
; area corner may only change the value recorded by 1 or 2 bits)
;
BBU_TCAL_DATA DCD 0,0,0,0 ; Touch panel calibration data
ENDFUNC
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -