@.CHARSET  CP1251

@ GNU AS
.syntax unified     @   
.thumb              @    Thumb
.cpu cortex-m3      @ 


.INCLUDE       "/src/inc/rcc.inc"
.INCLUDE       "/src/inc/gpio.inc"
.INCLUDE       "/src/devices/st7789/lcd_st7789.inc"    @  

@.DESC     name=ST7789_Init type=proc
@ +---------------------------------------------------------------------------+
@ |               ST7789            |
@ +---------------------------------------------------------------------------+
@ |        SPI      |
@ |                                                                           |
@ |   SPI   :            |
.EQU  spi_init      , SPI_TX_INIT    @    SPI     |
.EQU  spi_send      , SPI_TX_SEND    @           |
@ |                                    @ (   R4)           |
.EQU  spi_wait      , SPI_TXE_BSY_WAIT    @     |
@ |                                                                           |
@ |     (RST, DC, CS)    |
@ |   GPIO:                                                            |
.EQU  lcd_gpio_base , GPIOA_BASE    @  (xxx_BASE)  gpio           |
.EQU  gpio_enr_bit  , RCC_APB2ENR_IOPAEN_N    @    RCC_APB2ENR   |
@ |                                          spi_gpio_base |
@ |                                                                           |
@ |     (RST, DC, CS)      |
@ |    GPIO: 0..7  8..15,      |
@ |                                 |
.EQU  rst_pin       , 8          @    RST           |
.EQU  dc_pin        , 9          @    DC            |
.EQU  cs_pin        , 10         @    CS            |
@ |                                                                           |
@ |  :                                                            |
@ | - ST7789_INIT -             |
@ |                  . |
@ |               .                                     |
@ +---------------------------------------------------------------------------+
@.ENDDESC

@      GPIO
.IF            rst_pin > 7
.EQU  lcd_rst_pin   , rst_pin - 8
.EQU  lcd_dc_pin    , dc_pin - 8
.EQU  lcd_cs_pin    , cs_pin - 8
.EQU  gpio_crx      , GPIO_CRH    @     : GPIO_CRH   8..15
.ELSE
.EQU  lcd_rst_pin   , rst_pin
.EQU  lcd_dc_pin    , dc_pin
.EQU  lcd_cs_pin    , cs_pin
.EQU  gpio_crx      , GPIO_CRL    @     : GPIO_CRL   0..7
.ENDIF


.SECTION    .asmcode

register_prepare:   @       
                    @   bitband 
                    MOV             R1, 1
                    MOV             R0, 0

                    @  gpio     lcd
                    LDR             R2, = PERIPH_BASE + PERIPH_BB_BASE + ( lcd_gpio_base + GPIO_ODR ) * 32
                    BX              LR

.GLOBAL        ST7789_Init
ST7789_Init:        @     (spi)
                    PUSH            { LR }

                    BL              spi_init    @  SPI 

                    @   bitband 
                    MOV             R1, 1
                    MOV             R0, 0

                    @  gpio     lcd
                    LDR             R2, = PERIPH_BASE + PERIPH_BB_BASE + ( RCC_BASE + RCC_APB2ENR ) * 32
                    STR             R1, [ R2, gpio_enr_bit * 4 ]

                    @     GPIO
                    LDR             R2, = PERIPH_BASE + lcd_gpio_base
                    LDR             R4, [ R2, gpio_crx ]
                    MOV             R3, GPIO_MODE_OUT50
                    BFI             R4, R3, lcd_rst_pin * 4, 4
                    BFI             R4, R3, lcd_dc_pin * 4, 4
                    BFI             R4, R3, lcd_cs_pin * 4, 4
                    STR             R4, [ R2, gpio_crx ]

                    @     
                    LDR             R2, = PERIPH_BASE + PERIPH_BB_BASE + ( lcd_gpio_base + GPIO_ODR ) * 32
                    STR             R1, [ R2, rst_pin * 4 ]   @ RST=1
                    STR             R1, [ R2, cs_pin * 4 ]    @ CS=1    
                    STR             R0, [ R2, dc_pin * 4 ]    @ DC=0   ""

                    @     RST  
                    @         CS
                    STR             R0, [ R2, rst_pin * 4 ]    @ RST=0
                    MOV             R0, 1
                    BL              SYSTICK_DELAY
                    STR             R1, [ R2, rst_pin * 4 ]    @ RST=1
                    MOV             R0, 10
                    BL              SYSTICK_DELAY

                    @      
                    @ R0 = 0
                    @ R1 = 1
                    @ R2 = PERIPH_BASE + PERIPH_BB_BASE + ( lcd_gpio_base + GPIO_ODR ) * 32

                    @    ,     CS  
                    @     ,       (!!)  
                    @    CS
                    STR             R0, [ R2, cs_pin * 4 ]    @ CS=0  "" 

                    MOV             R4, ST7789_Cmd_SLPOUT    @ 0x11    
                    BL              LCD_SENDCOM
                    MOV             R0, 120
                    BL              SYSTICK_DELAY

                    MOV             R4, 0x36                 @ 0x36    90 
                    BL              LCD_SENDCOM              @   
                    MOV             R4, 0b011<<5             @ 0 < X < 319 , 0 < Y < 239
                    BL              spi_send                 @      

                    MOV             R4, ST7789_Cmd_COLMOD    @ 0x3A   16 
                    BL              LCD_SENDCOM
                    MOV             R4, ST7789_ColorMode_65K | ST7789_ColorMode_16bit
                    BL              spi_send

                    MOV             R4, ST7789_Cmd_INVON     @  
                    BL              LCD_SENDCOM

                    MOV             R4, ST7789_Cmd_DISPON    @ 0x29  
                    BL              LCD_SENDCOM

                    @    
                    STR             R1, [ R2, cs_pin * 4 ]    @ CS=1 -       

                    POP             { PC }


@.DESC     name=LCD_SENDCOM type=proc
@ ***************************************************************************
@ *                                            *
@ ***************************************************************************
@ | :                                                              |
@ |  R4 -                                                    |
@ +-------------------------------------------------------------------------+
@.ENDDESC
LCD_SENDCOM:        @       BSY
                    PUSH            { LR }
                    @ R0 = 0
                    @ R1 = 1
                    @ R2 = PERIPH_BASE + PERIPH_BB_BASE + ( lcd_gpio_base + GPIO_ODR ) * 32

                    BL              spi_wait                  @    

                    STR             R0, [ R2, dc_pin * 4 ]    @ DC=0   ""

                    BL              spi_send                  @   

                    BL              spi_wait                  @    

                    STR             R1, [ R2, dc_pin * 4 ]    @ DC=1   ""

                    POP             { PC }


@.DESC     name=LCD_AT type=proc
@ ***************************************************************************
@ *                                        *
@ ***************************************************************************
@ |                                          |
@ | :                                                              |
@ |  R5 -  X: 31:16 - SX, 15:0 - EX                               |
@ |  R6 -  Y: 31:16 - SY, 15:0 - EY                               |
@ +-------------------------------------------------------------------------+
@.ENDDESC
LCD_AT:             @    
                    PUSH            { R4, LR }

                    MOV             R4, ST7789_Cmd_CASET    @   StartX, EndX     
                    BL              LCD_SENDCOM      @  
                    UBFX            R4, R5, 24, 8    @  StartX
                    BL              spi_send
                    UBFX            R4, R5, 16, 8    @  StartX
                    BL              spi_send
                    UBFX            R4, R5, 8, 8     @  EndX
                    BL              spi_send
                    UBFX            R4, R5, 0, 8     @  EndX
                    BL              spi_send

                    MOV             R4, ST7789_Cmd_RASET    @   StartY, EndY      
                    BL              LCD_SENDCOM      @  
                    UBFX            R4, R6, 24, 8    @  StartY
                    BL              spi_send
                    UBFX            R4, R6, 16, 8    @  StartY
                    BL              spi_send
                    UBFX            R4, R6, 8, 8     @  EndY
                    BL              spi_send
                    UBFX            R4, R6, 0, 8     @  EndY
                    BL              spi_send

                    MOV             R4, ST7789_Cmd_RAMWR    @   
                    BL              LCD_SENDCOM

                    POP             { R4, PC }


@.DESC     name=ST7789_FILLRECT type=proc
@ ***************************************************************************
@ *                                        *
@ ***************************************************************************
@ |                                       |
@ | :                                                              |
@ |  R3 -                                                        |
@ |  R5 -  X: 31:16 - START_X, 15:0 - END_X                       |
@ |  R6 -  Y: 31:16 - START_Y, 15:0 - END_Y                       |
@ +-------------------------------------------------------------------------+
@.ENDDESC
.GLOBAL ST7789_FILLRECT
ST7789_FILLRECT:
                         PUSH        { R0, R1, R2, R4, R5, R6, R7, R8, LR }

                         BL          register_prepare

                         STR         R0, [ R2, cs_pin * 4 ]    @ CS=0  "" 

                         BL          LCD_AT        @      

                         @    Y
                         UBFX        R7, R6, 0, 16
                         UBFX        R8, R6, 16, 16
                         SUB         R7, R7, R8

                         @    X
                         UBFX        R8, R5, 0, 16
                         UBFX        R6, R5, 16, 16
                         SUB         R8, R8, R6

                         ADD         R5, R7, 1
                         ADD         R6, R8, 1
                         MUL         R5, R5, R6    @    

LCD_CLEAR_loop:
                         UBFX        R4, R3, 8, 8
                         BL          spi_send
                         UBFX        R4, R3, 0, 8
                         BL          spi_send

                         SUBS            R5, R5, 1
                         BNE         LCD_CLEAR_loop

                         BL          spi_wait

                         STR         R1, [ R2, cs_pin * 4 ]    @ CS=1   "" 

                         POP         { R0, R1, R2, R4, R5, R6, R7, R8, PC }


@.DESC     name=ST7789_PIXEL type=proc
@ +-------------------------------------------------------------------------+
@ |                                   |
@ +-------------------------------------------------------------------------+
@ |                                                                         |
@ |                                       |
@ |  :                                                      |
@ |    R0 -  Y [0..239],                                          |
@ |    R1 -  X [0..319],                                          |
@ |    R2 -                                                    |
@ |  :                                                  |
@ }    :                                       |
@ +-------------------------------------------------------------------------+
@.ENDDESC
.GLOBAL ST7789_PIXEL
ST7789_PIXEL:
                    PUSH            { R0, R1, R2, R3, R5, R6, LR }

                    MOV             R3, R2

                    ADD             R6, R0, R0, LSL 16
                    ADD             R5, R1, R1, LSL 16

                    BL              register_prepare
                    STR             R0, [ R2, cs_pin * 4 ]    @ CS=0  "" 

                    BL              LCD_AT

                     @  
                    UBFX            R4, R3, 8, 8
                    BL              spi_send
                    UBFX            R4, R3, 0, 8
                    BL              spi_send

                    BL              spi_wait

                    STR             R1, [ R2, cs_pin * 4 ]    @ CS=1   "" 

                    POP             { R0, R1, R2, R3, R5, R6, PC }


@.DESC     name=ST7789_CHAR_12x16 type=proc
@ ***************************************************************************
@ *                                                *
@ ***************************************************************************
@ |                                       |
@ | :                                                              |
@ |    LCD_CHAR: (R0:Y, R1:X, R2:Color, R3:Char) - native       |
@ +-------------------------------------------------------------------------+
@.ENDDESC

.GLOBAL ST7789_CHAR_12x16
ST7789_CHAR_12x16:
                    PUSH            { R0 - R9, LR }
                    @    
                    @   Y
                    ADD             R6, R0, R0, LSL 16
                    ADD             R6, R6, 15
                    @   X
                    ADD             R5, R1, R1, LSL 16
                    ADD             R5, R5, 11

                     @   
                    LDR             R4, = LCD_CHARS_12x16
                    SUB             R3, R3, 32

                    MOV             R7, 24
                    MUL             R3, R3, R7
                    ADD             R8, R4, R3             @  R8  

                    MOV             R3, R2                 @  

                    @     
                    BL              register_prepare
                    STR             R0, [ R2, cs_pin * 4 ]    @ CS=0  "" 
                    BL              LCD_AT

                    @ R1 - 2  
                    @ R3 -     
                    @ R6 -     
                    @ R7 -  
                    MOV             R6, 12
LCD_line_loop_12x16:
                      @    
                    MOV             R7, 16
                    LDRSH           R9, [ R8 ], 2
LCD_pix_loop_12x16:
                     @   
                    TST             R9, 0x8000
                    ITE             EQ
                    UBFXEQ          R5, R3, 0, 16
                    UBFXNE          R5, R3, 16, 16
                     @  
                    UBFX            R4, R5, 8, 8
                    BL              spi_send
                    UBFX            R4, R5, 0, 8
                    BL              spi_send
                     @    
                    LSL             R9, R9, 1
                     @    ( )
                    SUBS            R7, R7, 1
                    BNE             LCD_pix_loop_12x16
                     @    (  )
                    SUBS            R6, R6, 1
                    BNE             LCD_line_loop_12x16

                    BL              spi_wait

                    STR             R1, [ R2, cs_pin * 4 ]    @ CS=1   "" 

                    POP             { R0 - R9, PC }

.INCLUDE "/src/devices/ST7789/font12x16.inc"
