/*
* RGǴpolis: la capital de RGG
* Copyright (C) 2022 Iván Alejandro Ávalos Díaz <avalos@disroot.org>,
* Fernando Daniel Hernández López <18030953>,
* Uciel Eguiluz López <18031804>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Prólogo de función no hoja */
.macro proc
push {r11, lr}
add r11, sp, #0
sub sp, sp, #16
.endm
/* Epílogo de función no hoja */
.macro endp
sub sp, r11, #0
pop {r11, pc}
.endm
/* Sección de datos */
.data
width: .word 128
height: .word 128
offsetx: .word 0
offsety: .word 0
r: .byte 0
g: .byte 0
b: .byte 0
bmp: .word 0
/* Sección de código */
.text
.global main
/*
* init_lcd
*/
init_lcd:
proc
/* lcdInit (width, height, offsetx, offsety) */
ldr r4, _width
ldr r0, [r4]
ldr r4, _height
ldr r1, [r4]
ldr r4, _offsetx
ldr r2, [r4]
ldr r4, _offsety
ldr r3, [r4]
bl lcdInit(PLT)
bl lcdReset(PLT) // lcdReset ()
bl lcdSetup(PLT) // lcdSetup ()
/* lcdFillScreen (WHITE) */
movw r0, #0xFFFF
bl lcdFillScreen(PLT)
endp
/*
* bitmap_open
* r0 = filename
*/
bitmap_open:
proc
/* bmp = bopen (filename) */
bl bopen(PLT)
ldr r4, _bmp
str r0, [r4]
endp
/*
* bitmap_close
*/
bitmap_close:
proc
/* bclose (bmp) */
ldr r4, _bmp
ldr r0, [r4]
bl bclose(PLT)
endp
/*
* bitmap_display
*/
bitmap_display:
proc
/* Escribir datos de pixeles al framebuffer */
/* Fuente: https://github.com/nopnop2002/Raspberry-ili9340spi/issues/22 */
/* lcdWriteCommandByte (0x2A) */
mov r0, #0x2A
bl lcdWriteCommandByte(PLT)
/* lcdWriteDataWord (0) */
mov r0, #0
bl lcdWriteDataWord(PLT)
/* lcdWriteDataWord (width - 1) */
ldr r4, _width
ldr r4, [r4]
sub r0, r4, #1 // width - 1
bl lcdWriteDataWord(PLT)
/* lcdWriteCommandByte (0x2B) */
mov r0, #0x2B
bl lcdWriteCommandByte(PLT)
/* lcdWriteDataWord (0) */
mov r0, #0
bl lcdWriteDataWord(PLT)
/* lcdWriteDataWord (height - 1) */
ldr r4, _height
ldr r4, [r4]
sub r0, r4, #1 // height - 1
bl lcdWriteDataWord(PLT)
/* lcdWriteCommandByte (0x2C) */
mov r0, #0x2C
bl lcdWriteCommandByte(PLT)
/* width */
ldr r8, _width
ldr r8, [r8]
/* height */
ldr r9, _height
ldr r9, [r9]
/* Bucle para y */
mov r6, #0 // y = 0
loopHeight:
cmp r6, r9 // y == height
beq loopHeightEnd
/* Bucle para x */
mov r5, #0 // x = 0
loopWidth:
cmp r5, r8 // x == width
beq loopWidthEnd
/* get_pixel_rgb (bmp, x, height - y, &r, &g, &b) */
/* Parámetros por registro (0-3) */
ldr r4, _bmp
ldr r0, [r4] // bmp
mov r1, r5 // x
sub r2, r8, r6 // height - y
ldr r3, _r // &r
/* Parámetros por pila (4-5) */
ldr r4, _g
str r4, [sp] // &g
ldr r4, _b
str r4, [sp, #4] // &b
bl get_pixel_rgb(PLT)
/* Convertir RGB888 a RGB565 */
/* Fuente: https://afterthoughtsoftware.com/posts/convert-rgb888-to-rgb565 */
ldr r4, _b
ldr r4, [r4]
mov r1, r4 // b
lsr r1, r1, #3 // b >> 3
and r1, r1, #0x1F // (b >> 3) & 0x1f
ldr r4, _g
ldr r4, [r4]
mov r2, r4 // g
lsr r2, r2, #2 // g >> 2
and r2, r2, #0x3F // (g >> 2) & 0x3f
lsl r2, r2, #5 // ((g >> 2) & 0x3f) << 5
ldr r4, _r
ldr r4, [r4]
mov r3, r4 // r
lsr r3, r3, #3 // r >> 3
and r3, r3, #0x1F // (r >> 3) & 0x1f
lsl r3, r3, #11 // ((r >> 3) & 0x1f) << 11
mov r0, r1 // out = B
orr r0, r0, r2 // out |= G
orr r0, r0, r3 // out |= R
bl lcdWriteDataWord(PLT)
add r5, r5, #1
b loopWidth
loopWidthEnd:
/* Fin del bucle para x */
add r6, r6, #1
b loopHeight
loopHeightEnd:
/* Fin del bucle para y */
endp
/*
* main
* r0 = argc
* r1 = argv
*/
main:
proc
push {r1} // argv
bl init_lcd // init_lcd ()
/* bitmap_open (argv[1]) */
pop {r0} // argv
ldr r0, [r0, #4] // argv[1]
bl bitmap_open
bl bitmap_display // bitmap_display ()
bl bitmap_close // bitmap_close ()
/* return (0) */
mov r0, #0
endp
/* Puentes para acceder a sección .data desde .text */
_width: .word width
_height: .word height
_offsetx: .word offsetx
_offsety: .word offsety
_bmp: .word bmp
_r: .word r
_g: .word g
_b: .word b