@.CHARSET  CP1251

@ GNU AS
.SYNTAX   unified
.CPU      cortex-m3
.THUMB

.INCLUDE   "/src/inc/rcc.inc"
.INCLUDE   "/src/inc/gpio.inc"

@.DESC     name=LCD5110_Init type=proc
@ +---------------------------------------------------------------------------+
@ |               PCD8544           |
@ +---------------------------------------------------------------------------+
@ |        SPI      |
@ |                                                                           |
@ |   SPI   :            |
.EQU  spi_init      , SPI_TX_INIT      @    SPI   |
.EQU  spi_send      , SPI_TX_SEND      @         |
@ |                                    @ (   R4)           |
@ |                                                                           |
@ |     (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    |
@ |                                                                           |
@ |  :                                                            |
@ | - LCD5110_INIT -            |
@ |                  . |
@ |               .                                     |
@ +---------------------------------------------------------------------------+
@ |    :                                             |
@ |                                                                           |
@ | https://youtu.be/YjQJV2QvacQ                                              |
@ | ArmAsmEditor: STM32  :  .  15        |
@ |                                                                           |
@ | https://youtu.be/fxBM0pA7Ucw                                              |
@ | ArmAsmEditor: STM32  :   - .    |
@ |  LCD 5110.  17                                                      |
@ |                                                                           |
@ | https://youtu.be/6RA9iviSBw0                                              |
@ | ArmAsmEditor: STM32  :   - .   |
@ |  LCD 5110.  18                                                      |
@ +---------------------------------------------------------------------------+
@.ENDDESC

@.ITEM     APB2PERIPH_BASE_USER
.EQU  GPIOA_BASE         , APB2PERIPH_BASE + 0x0800  @ GPIO A
.EQU  GPIOB_BASE         , APB2PERIPH_BASE + 0x0C00  @ GPIO B
.EQU  GPIOC_BASE         , APB2PERIPH_BASE + 0x1000  @ GPIO C
.EQU  GPIOD_BASE         , APB2PERIPH_BASE + 0x1400  @ GPIO D
.EQU  GPIOE_BASE         , APB2PERIPH_BASE + 0x1800  @ GPIO E
.EQU  GPIOF_BASE         , APB2PERIPH_BASE + 0x1C00  @ GPIO F
.EQU  GPIOG_BASE         , APB2PERIPH_BASE + 0x2000  @ GPIO G
@.end

@.ITEM     RCC_APB2ENR_USER
.EQU  RCC_APB2ENR_IOPAEN_N, 2      @ GPIO A Enable Bit
.EQU  RCC_APB2ENR_IOPBEN_N, 3      @ GPIO B Enable Bit
.EQU  RCC_APB2ENR_IOPCEN_N, 4      @ GPIO C Enable Bit
.EQU  RCC_APB2ENR_IOPDEN_N, 5      @ GPIO D Enable Bit
.EQU  RCC_APB2ENR_IOPEEN_N, 6      @ GPIO E Enable Bit
.EQU  RCC_APB2ENR_IOPFEN_N, 7      @ GPIO F Enable Bit
.EQU  RCC_APB2ENR_IOPGEN_N, 8      @ GPIO G Enable Bit
@.END

@.CONFIG lcd_gpio_base=APB2PERIPH_BASE_USER  gpio_enr_bit=RCC_APB2ENR_USER

@      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

.GLOBAL   LCD5110_Init
LCD5110_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        R0, [ R2, dc_pin * 4 ]    @ DC=0   ""
                    STR        R0, [ R2, cs_pin * 4 ]    @ CS=0  ""

                    @     RST  
                    STR        R0, [ R2, rst_pin * 4 ]   @ RST=0
                    BL         INIT_Pause
                    STR        R1, [ R2, rst_pin * 4 ]   @ RST=1
                    BL         INIT_Pause

                    @      
                    @ . 22 \Add\MCUDoc\LCD\Nokia5110.pdf
                    MOV        R4, 0x21
                    BL         spi_send

                    MOV        R4, 0x90
                    BL         spi_send

                    MOV        R4, 0x20
                    BL         spi_send

                    MOV        R4, 0x0C
                    BL         spi_send

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

                    POP        { PC }


INIT_Pause:         @   ,    
                    MOV        R3, 0x1000
INIT_Pause_Loop:
                    SUBS       R3, R3, 1
                    BNE        INIT_Pause_Loop
                    BX         LR



@.DESC     name=LCD5110_REFRESH type=proc
@ +-------------------------------------------------------------------------+
@ |                   SRAM  LCD                     |
@ +-------------------------------------------------------------------------+
@ |                                                                         |
@ |             SRAM    LCD  |
@ |                                                              |
@ |                                                                         |
@ |  :                                                   |
@ |                                                                         |
@ |  :                                                  |
@ |                                                                         |
@ }    :                                       |
@ |                                                                         |
@ +-------------------------------------------------------------------------+
@.ENDDESC

.SECTION .bss           @    SRAM
.align      ( 4 )
LCD_BUFF:               .space      84 * 6, 0

.SECTION .asmcode

.GLOBAL LCD5110_REFRESH
LCD5110_REFRESH:
@   ()
                    PUSH       { R0, R1, R2, R3, R4, R5, LR }
                    MOV        R0, 0
                    MOV        R1, 1

                    LDR        R2, = PERIPH_BASE + PERIPH_BB_BASE + ( lcd_gpio_base + GPIO_ODR ) * 32

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

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

                    MOV        R4, 0x40           @ YPos=0
                    BL         spi_send

                    MOV        R4, 0x80           @ XPos=0
                    BL         spi_send

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

                    MOV        R3, 84 * 6         @      
                    LDR        R5, = LCD_BUFF     @   

Refresh_loop:
                    LDRB       R4, [ R5 ], 1      @    , 
                    BL         spi_send           @    SPI

                    SUBS       R3, R3, 1          @      84*6   
                    BNE        Refresh_loop       @

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

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


@.DESC     name=LCD5110_CLEAR type=proc
@ +-------------------------------------------------------------------------+
@ |                                                     |
@ +-------------------------------------------------------------------------+
@ |                                                                         |
@ |           ,      |
@ |  (   LCD5110_Refresh)                          |
@ |                                                                         |
@ |  :                                                   |
@ |                                                                         |
@ |  :                                                  |
@ |                                                                         |
@ }    :                                       |
@ |                                                                         |
@ +-------------------------------------------------------------------------+
@.ENDDESC

.GLOBAL LCD5110_CLEAR
LCD5110_CLEAR:
                    PUSH       { R0, R1, R2 }


                    MOV        R1, 84 * 6         @     

                    LDR        R2, = LCD_BUFF     @  
                    MOV        R0, 0x00           @  

Clear_loop:         @     4  ( )
                    STR        R0, [ R2 ], 4    @     

                    SUBS       R1, R1, 4
                    BNE        Clear_loop

                    POP        { R0, R1, R2 }
                    BX         LR


@.DESC     name=LCD5110_PIXEL type=proc
@ +-------------------------------------------------------------------------+
@ |                                   |
@ +-------------------------------------------------------------------------+
@ |                                                                         |
@ |              |
@ | .                                                                 |
@ |     ,    LCD5110_Refresh     |
@ |                                                                         |
@ |  :                                                      |
@ |    R0 -  Y [0..47],                                           |
@ |    R1 -  X [0..83],                                           |
@ |                                                                         |
@ |  :                                                  |
@ |                                                                         |
@ }    :                                       |
@ |                                                                         |
@ +-------------------------------------------------------------------------+
@.ENDDESC

.GLOBAL LCD5110_PIXEL
LCD5110_PIXEL:
                    PUSH       { R0, R1, R3, R4, R5 }

                    @    
                    CMP        R0, 48
                    BPL        LCD_PIXEL_exit
                    CMP        R1, 84
                    BPL        LCD_PIXEL_exit

                    @   
                    LSR        R3, R0, 3          @  y >> 3 -       
                    MOV        R4, 84
                    MUL        R3, R3, R4         @ (y >> 3) * 84         84   
                    ADD        R5, R3, R1         @ (y >> 3) * 84 + x    

                    LDR        R4, = LCD_BUFF
                    ADD        R5, R5, R4         @  R5  

                    LDRB       R4, [ R5 ]         @      

                    @         (    Y)
                    MOV        R3, 1
                    AND        R0, R0, 0x07      @     
                    LSL        R3, R3, R0

                    ORR        R4, R4, R3         @   - OR  

                    STRB       R4, [ R5 ]         @   

LCD_PIXEL_exit:
                    POP        { R0, R1, R3, R4, R5 }
                    BX         LR

@.DESC     name=LCD5110_CHAR type=proc
@ +-------------------------------------------------------------------------+
@ |                                                             |
@ +-------------------------------------------------------------------------+
@ |                                                                         |
@ |              |
@ | .                                                                 |
@ |     ,    LCD5110_Refresh     |
@ |                                                                         |
@ |  :                                                      |
@ |    R0 -  Y [0..47],                                           |
@ |    R1 -  X [0..83],                                           |
@ |    R2 -  (0: , 1: )                                   |
@ |    R3 -                                             |
@ |                                                                         |
@ |  :                                                  |
@ |                                                                         |
@ }    :                                       |
@ |                                                                         |
@ +-------------------------------------------------------------------------+
@.ENDDESC

.INCLUDE  "/src/devices/pcd8544/font6x8.inc"                 @  

.GLOBAL LCD5110_CHAR
LCD5110_CHAR:
                         PUSH        { R0 - R12, LR }

                         CMP         R0, 48                  @   
                         BPL         LCD_CHAR_exit
                         CMP         R1, 84
                         BPL         LCD_CHAR_exit

                         CMP         R2, 0                   @    
                         BNE         LCD_CHAR_noleftline     @  

                      @     
                         PUSH        { R0, R1 }
                         MOV         R4, 9                   @     
                         SUB         R1, R1, 1               @  
                         SUB         R0, R0, 1               @    

LCD_CHAR_leftline:
                         BL          LCD5110_PIXEL
                         ADD         R0, R0, 1
                         SUBS        R4, R4, 1
                         BNE         LCD_CHAR_leftline        @   
                         POP         { R0, R1 }

LCD_CHAR_noleftline:
          @   char   
                         CMP         R3, 127
                         ITTEE       MI
                         ADRMI       R12, LCD_LAT_CHARS
                         SUBMI       R3, R3, 32
                         ADRPL       R12, LCD_RUS_CHARS   @  
                         SUBPL       R3, R3, 192          @     ,

                         AND         R4, R0, 0x07            @  R4        

                         LSR         R5, R0, 3               @  R5    Y  

                   @   -   
                         LDR         R9, = LCD_BUFF         @     
                         MOV         R7, 84                 @   
                         MUL         R7, R7, R5             @    (   8 )   Y
                         ADD         R9, R9, R7
                         ADD         R9, R9, R1              @    8      

           @ R0  :  Y
           @ R1  :  X
           @ R2  :  
           @ R3  :     ,
           @ R4  :        
           @ R5  :    Y  
           @ R9  :      
           @ R12 :  
                         MOV         R6, 0                   @   (    = 6 [0..5])
LCD_CHAR_loop:
                         MOV         R7, 6                   @      
                         MUL         R8, R3, R7              @  (R8)=  (R3) * 6 (R7)

                         ADD         R8, R8, R6              @    (R6)  [0..6]
                         ADD         R8, R8, R12             @       R8 
                                                             @ -      
                         LDRB        R8, [ R8 ]              @   ( )

                         CMP         R2, 0                   @    
                         BNE         LCD_CHAR_noinv
                         RSB         R8, R8, 0xFF            @   
                         PUSH        { R0 }
                         SUB         R0, R0, 1               @    
                         BL          LCD5110_PIXEL               @  
                         POP         { R0 }

LCD_CHAR_noinv:
                      @    
                         LSL         R11, R8, R4            @        R10 
                         LDRB        R10, [ R9 ]             @    
                         ORR         R11, R10, R11           @      
                         STRB        R11, [ R9 ]             @  

                       @    
                         CMP         R4, 0                   @    
                         BEQ         LCD_CHAR_loop_end       @   

                         CMP         R5, 5                   @    
                         BEQ         LCD_CHAR_loop_end       @    

                         ADD         R7, R9, 84

                         RSB         r10, r4, 8
                         LSR         R11, R8, R10             @   

                         LDRB        R10, [ R7 ]              @     
                         ORR         R11, R10, R11            @    
                         STRB        R11, [ R7 ]              @     

LCD_CHAR_loop_end:
                         ADD         R1, R1, 1                @ X=X+1
                         CMP         R1, 84
                         BPL         LCD_CHAR_exit

                         ADD         R9, R9, 1                @       
                         ADD         R6, R6, 1                @      
                         CMP         R6, 6                    @    6  
                         BNE         LCD_CHAR_loop            @  

LCD_CHAR_exit:
                         POP         { R0 - R12, PC }


