GeneraV
Posts: 31
Joined: Mon Feb 04, 2013 2:10 am

Set screen resolution

Tue Mar 12, 2013 6:00 pm

Hi all
I've been getting myself in a right twist trying to set the screen resolution on my raspberry!
All I've been getting is 1024x768 and a box of various colours (depending on how I mess
about with the code). The code is based on Dex and Krom's code. It's just quick and dirty to
get things up and running. Before I forget the config.txt is set to hdmi_safe=1.
Any help would be appreciated :D

Code: Select all

;;; Test program for displaying screen resolutions
;;; for the Raspberry Pi.
format binary as 'img'
macro store reg,immediate {                              ;
mov reg,immediate and $FF                                ;
orr reg,reg,immediate and $FF00                          ;
orr reg,reg,immediate and $FF0000                        ;
orr reg,reg,immediate and $FF000000                      ;
}

SCREEN_WIDTH=800
SCREEN_HEIGHT=600
BITS_PER_PIXEL=8
PERIPHERAL_BASE_ADDRESS=0x2000b880

BUS_ADDRESSES_l2CACHE_ENABLED=0x40000000
MAIL_BOX_BASE_ADDRESS=0xb880
MAIL_BOX_WRITE=0x20
MAIL_BOX_READ=0x00
MAIL_BOX_CHANNEL_1_FRAMEBUFFER=0x1
org 0x8000+BUS_ADDRESSES_l2CACHE_ENABLED
mov sp, 0x8000
FrameBufferInit:        store r0, PERIPHERAL_BASE_ADDRESS;+MAIL_BOX_BASE_ADDRESS
                        store r1, FRAME_BUFFER_STRUCTURE
                        orr r1, MAIL_BOX_CHANNEL_1_FRAMEBUFFER
                        str r1, [r0, MAIL_BOX_WRITE+MAIL_BOX_CHANNEL_1_FRAMEBUFFER]
;
FrameBufferRead:        ldr r1, [r0, MAIL_BOX_READ]
                        tst r1, MAIL_BOX_CHANNEL_1_FRAMEBUFFER
                        beq FrameBufferRead

                        store r1, FRAME_BUFFER_POINTER
                        ldr r0, [r1]
                        cmp r0, 0
                        beq FrameBufferInit
Loop:                   b Loop
align 16
FRAME_BUFFER_STRUCTURE:
        dw SCREEN_WIDTH         ;;; Frame buffer pixel width
        dw SCREEN_HEIGHT        ;;; Frame buffer pixel height
        dw SCREEN_WIDTH         ;;; Frame buffer virtual pixel width
        dw SCREEN_HEIGHT        ;;; Frame buffer virtual pixel height
        dw 0                    ;;; Frame buffer pitch (set by GPU)
        dw BITS_PER_PIXEL       ;;; Frame buffer pits per pixel
        dw 0                    ;;; Frame buffer offset in X direction
        dw 0                    ;;; Frame buffer offset in Y direction
FRAME_BUFFER_POINTER:
        dw 0                    ;;; Frame buffer pointer (set by GPU)
        dw 0                    ;;; Frame buffer size (set by GPU)

User avatar
DexOS
Posts: 876
Joined: Wed May 16, 2012 6:32 pm
Contact: Website

Re: Set screen resolution

Wed Mar 13, 2013 12:45 am

Why is there a ; in this line

Code: Select all

store r0, PERIPHERAL_BASE_ADDRESS;+MAIL_BOX_BASE_ADDRESS
It should be

Code: Select all

store r0, PERIPHERAL_BASE_ADDRESS+MAIL_BOX_BASE_ADDRESS
Anything after a ; is ignored in fasm, for adding stuff like comments.

Also your best using this macro

Code: Select all

macro store reg,immediate {
  mov reg,(immediate) and $FF
  orr reg,(immediate) and $FF00
  orr reg,(immediate) and $FF0000
  orr reg,(immediate) and $FF000000
}

Also see kroms hello world demo, cpu ver, as 8bit users a palette.
Also note: 8 bit seem to to be a bit fuzzy on some pixels like fonts on the pi.
Batteries not included, Some assembly required.

GeneraV
Posts: 31
Joined: Mon Feb 04, 2013 2:10 am

Re: Set screen resolution

Wed Mar 13, 2013 1:47 am

I should have taken out the ;+MAIL_BOX_BASE_ADDRESS as I just added togther the 2 values myself.
Just tried to use 16bits for each pixel still no joy :cry: I know my tv is capable of 1920x1080 (I've had risc os running) This seems very strange! I've used the latest firmware and your older firmware (dex).

User avatar
DexOS
Posts: 876
Joined: Wed May 16, 2012 6:32 pm
Contact: Website

Re: Set screen resolution

Wed Mar 13, 2013 2:41 am

GeneraV wrote:I should have taken out the ;+MAIL_BOX_BASE_ADDRESS as I just added togther the 2 values myself.
Just tried to use 16bits for each pixel still no joy :cry: I know my tv is capable of 1920x1080 (I've had risc os running) This seems very strange! I've used the latest firmware and your older firmware (dex).
Here is some test code in DexBasic
http://www.dex-os.com/DexOS_R_PI/TestRes.zip
That sets the res
Does that work ?
More info on using DexBasic
http://www.dex-os.com/DexBasic/DexBasic.htm

you may need to add
disable_overscan=1
to your config.txt
Batteries not included, Some assembly required.

GeneraV
Posts: 31
Joined: Mon Feb 04, 2013 2:10 am

Re: Set screen resolution

Wed Mar 13, 2013 6:35 pm

Downloaded your screen resolution test, had no config.txt, used latest firmware files. It displayed a white screen but it filled the entire screen unlike my tests which had big black border at both sides!
My tv still says 1076x786! I might have a play around with the config.txt as you suggested. I'll poke around in the source code downloaded to see what knowledge I can aquire. I'll post the results later. I can't believe it's this hard to get something so simple up and running effectively. But at least the black boarders have gone.

User avatar
rpdom
Posts: 14686
Joined: Sun May 06, 2012 5:17 am
Location: Chelmsford, Essex, UK

Re: Set screen resolution

Wed Mar 13, 2013 6:54 pm

I haven't tried your code, but I've been having a real headache trying to set up the Frame Buffer the way I want it. Finally got it cracked (the code, not my head) I think and have been running at various resolutions (up to the 1024x768 that my monitor supports), at 16, 8 and even 4bpp :-)

Next challenge is to get a timer driven interrupt routine working :?

BTW, I don't use dexbasic or anything like that, just plain ARM assembler and gas. May not be great, but I can cope with it :)

GeneraV
Posts: 31
Joined: Mon Feb 04, 2013 2:10 am

Re: Set screen resolution

Wed Mar 13, 2013 9:56 pm

Hi rpdom
Could you please post your code :) I've been using FasmArm. It's just a pity their isn't a 1 stop shop on how to do the basics (besides the Cambridge university course http://www.cl.cam.ac.uk/freshers/raspbe ... orials/os/) . I suppose things are complicated by the firmware. Can't wait for it to stablise :D

User avatar
DexOS
Posts: 876
Joined: Wed May 16, 2012 6:32 pm
Contact: Website

Re: Set screen resolution

Thu Mar 14, 2013 1:01 am

This is the FasmArm code, of the dexbasic demo i posted, its strip down to the bare mini
kernel.asm

Code: Select all

; -------------------------------------------------------
; Pi def's
; -------------------------------------------------------
BUS_ADDRESSES                   = 0xC0000000             ;                                              ;
BUS_ADDRESSES_l2CACHE_DISABLED  = BUS_ADDRESSES          ;
BUS_ADDRESSES_l2CACHE_ENABLED   = 0x40000000             ;
PERIPHERAL_BASE                 = 0x20000000             ;
;Mail Box                                                ;
MAIL_BASE                       = 0xB880                 ;
MAIL_READ                       = 0x00                   ; We read from this register
MAIL_WRITE                      = 0x20                   ; This is where we write to; it is actually the read/write of the other mailbox
MAIL_STATUS                     = 0x18                   ;
MAIL_EMPTY                      = 0x40000000             ; This bit is set if there is nothing to read from the mailbox
MAIL_FULL                       = 0x80000000             ; This bit is set in the status register if there is no space to write into the mailbox
MAIL_FB                         = 1                      ; The frame buffer uses channel 1
ScreenSize                      =  1920 *1080 /2         ; CHANGE IF YOU CHANGE SCREEN RES
; -------------------------------------------------------
; fasm arm macro
; -------------------------------------------------------
macro imm32 reg,immediate {                              ;
  mov reg,(immediate) and $FF                            ;
  orr reg,(immediate) and $FF00                          ;
  orr reg,(immediate) and $FF0000                        ;
  orr reg,(immediate) and $FF000000                      ;
}                                                        ;
; -------------------------------------------------------
; kernel start
; -------------------------------------------------------
format binary as 'img'                                   ;
org     0x008000                                         ;
use32                                                    ;
; -------------------------------------------------------
; Start
; -------------------------------------------------------
Start:                                                   ;
   b   MainStart                                         ;
times 0x008000- ($-Start)  db 0                          ;
MainStart:                                               ;
; -------------------------------------------------------
; set screem Res  and frame buffer
; -------------------------------------------------------
        mov    sp,0x8000                                 ; set stackup
        imm32  r0,1920                                   ; set screen x
        imm32  r1,1080                                   ; set screen y
        imm32  r2,16                                     ; set BPP
        bl     Screen                                    ; call function
; -------------------------------------------------------
; Fill offscreen buffer
; -------------------------------------------------------
        imm32  r0,1920                                   ;
        imm32  r1,1080                                   ;
        mul    r2,r0,r1                                  ; set screen fill size
        mov    r2, r2, lsr 1                             ; devide by 2 as we are writting 4 pixels
        imm32  r0,0xffffffff                             ; set color
        imm32  r1,ScrBuffer                              ; buffer address
align 4                                                  ;
FillOffScrBuff:                                          ;
        str    r0,[r1],4                                 ;
        subs   r2,r2, 1                                  ;
        bne    FillOffScrBuff                            ;
; -------------------------------------------------------
; Write off screen buffer to screen
; -------------------------------------------------------
        bl     WriteOffScrBuff2screen                    ;
; -------------------------------------------------------
; just loop
; -------------------------------------------------------
DoTheLoopyLoop:                                          ;
        b      DoTheLoopyLoop                            ;
; -----------------------------------------------------  ;
;  Set new screen size                                   ;
; -----------------------------------------------------  ;
; Input:                                                 ;
;     R0 = NEW X                                         ;
;     R1 = NEW Y                                         ;
;     R2 = NEW Bits Per Pixel                            ;
; -----------------------------------------------------  ;
Screen:                                                  ;
        stmfd  sp!, {r0-r11, r12, lr}                    ; Store registers
        imm32  r6,SetFB_X                                ; Save X
        str    r0,[r6]                                   ;
        imm32  r6,SetFB_Y                                ; Save Y
        str    r1,[r6]                                   ;
        imm32  r6,SetFB_BPP                              ;
        str    r2,[r6]                                   ;
TryInitFb_Again:                                         ; Should add time out here.
        bl    TryInitFb                                  ;
        cmp   r0,0                                       ;
        bne   TryInitFb_Again                            ;
        ldmfd  sp!, {r0-r11, r12, pc}                    ; Restore registers and return
align 4                                                  ;
; -----------------------------------------------------  ;
; MailBox write                                          ;
; -----------------------------------------------------  ;
SetUpBufferStructure:                                    ;
        stmfd  sp!,{r0-r11, r12, lr}                     ; Store registers
        mov    r0,1                                      ;
        imm32  r0,0xA00000                               ; 10MB
        imm32  r1,SetFB_X                                ;
        ldr    r1,[r1]                                   ;
        str    r1,[r0],4                                 ;
        imm32  r1,SetFB_Y                                ;
        ldr    r1,[r1]                                   ;
        str    r1,[r0],4                                 ;
        imm32  r1,SetFB_X                                ;
        ldr    r1,[r1]                                   ;
        str    r1,[r0],4                                 ;
        imm32  r1,SetFB_Y                                ;
        ldr    r1,[r1]                                   ;
        str    r1,[r0],4                                 ;
        mov    r1,0                                      ;
        str    r1,[r0],4                                 ;
        imm32  r1,SetFB_BPP                              ;
        ldr    r1,[r1]                                   ;
        str    r1,[r0],4                                 ;
        mov    r1,0                                      ;
        str    r1,[r0],4                                 ;
        mov    r1,0                                      ;
        str    r1,[r0],4                                 ;
        mov    r1,0                                      ;
        str    r1,[r0],4                                 ;
        mov    r1,0                                      ;
        str    r1,[r0],4                                 ;
                                                         ;
        ldmfd  sp!,{r0-r11, r12, pc}                     ; Restore registers and return
align 4                                                  ;
; -----------------------------------------------------  ;
; MailBox write                                          ;
; -----------------------------------------------------  ;
MBox_Write:                                              ;
        stmfd  sp!,{r0-r11, r12, lr}                     ; Store registers
align 4                                                  ;
MBox_Write_Loop1:                                        ;
        imm32  r1,PERIPHERAL_BASE + MAIL_BASE + MAIL_STATUS ; read MAIL_STATUS
        ldr    r0,[r1]                                   ; read that address
        and    r0,r0,MAIL_FULL                           ; and the retrun read
        cmp    r0,MAIL_FULL                              ; test if mail full bit set
        beq    MBox_Write_Loop1                          ; if so try again
                                                         ;
        bl     SDelay                                    ;
                                                         ;
        imm32  r0,0xA00000 + BUS_ADDRESSES_l2CACHE_ENABLED ;
        orr    r0,r0,1                                   ;
        imm32  r1,PERIPHERAL_BASE + MAIL_BASE + MAIL_WRITE + MAIL_FB ; write to MAIL_WRITE
        str    r0,[r1]                                   ; store whats in r0 into address r1
        ldmfd  sp!,{r0-r11, r12, pc}                     ; Restore registers and return
align 4                                                  ;
; -----------------------------------------------------  ;
; MailBox read                                           ;
; -----------------------------------------------------  ;
MBox_Read:                                               ;
        stmfd  sp!,{r0-r3, r12, lr}                      ; Store registers
align 4                                                  ;
MBox_Read_loop1:                                         ;
        imm32  r1,PERIPHERAL_BASE + MAIL_BASE + MAIL_STATUS ; read MAIL_STATUS
        ldr    r0,[r1]                                   ; read that address
        and    r0,r0,MAIL_EMPTY                          ; and the retrun read
        cmp    r0,MAIL_EMPTY                             ; test if 0 or not
        beq    MBox_Read_loop1                           ; not empty loop
                                                         ;
        bl     SDelay                                    ;
                                                         ;
        imm32  r1,PERIPHERAL_BASE + MAIL_BASE + MAIL_READ;
        ldr    r0,[r1]                                   ; read that address
        mov    r4,r0                                     ; save value
        and    r0,r0,0xf                                 ; and the retrun read
        cmp    r0,MAIL_FB                                ;
        bne    MBox_Read_loop1                           ; jump not =
        and    r4,r4,0xFFFFFFF0                          ;
        ldmfd  sp!,{r0-r3, r12, pc}                      ; Restore registers and return
align 4                                                  ;
; -----------------------------------------------------  ;
; TryInitFb                                              ;
; -----------------------------------------------------  ;
TryInitFb:                                               ;
        stmfd  sp!,{r1-r8, r12, lr}                      ; Store registers
align 4                                                  ;
        bl     SetUpBufferStructure                      ;
align 4                                                  ;
        bl     MBox_Write                                ; Tell the GPU the address of the structure memory
align 4                                                  ;
        bl     SDelay                                    ; try delay ?
        bl     MBox_Read                                 ; Wait for the GPU to respond, and get its response
        cmp    r4,0                                      ;
        bne    ErrorExit                                 ;
align 4                                                  ;
        imm32  r0,0xA00020                               ; Load r0 with address of screen buffer.
        ldr    r0,[r0]                                   ;
        cmp    r0,0                                      ; test if framebuffer is empty
        beq    ErrorExit                                 ; If empty, do not try to write to buffer.
align 4                                                  ;
OkExit:                                                  ;
        mov    r0,0                                      ; OK
        ldmfd  sp!,{r1-r8, r12, pc}                      ; Restore registers and return
ErrorExit:                                               ;
        mov    r0,1                                      ; error
        ldmfd  sp!,{r1-r8, r12, pc}                      ; Restore registers and return
align 4                                                  ;
; -----------------------------------------------------  ;
; Write Off Screen Buffer to screen                      ;
; -----------------------------------------------------  ;
WriteOffScrBuff2screen:                                  ;
        stmfd  sp!,{r0-r11, r12, lr}                     ; Store registers
        imm32  r0,0xA00020                               ;
        ldr    r0,[r0]
        imm32  r2,ScreenSize                             ; Load r2, with number of times to loop  640*480
        imm32  r1,ScrBuffer                              ;
align 4                                                  ; -
WriteOffScrBuff2screenLoop:                              ; -
        ldmia  r1!,{r3 - r10}                            ; -
        stmia  r0!,{r3 - r10}                            ; -
        subs   r2,r2,8                                   ; -
        bge    WriteOffScrBuff2screenLoop                ; -
        ldmfd  sp!,{r0-r11, r12, pc}                     ; Restore registers and return
align 4                                                  ;
; -----------------------------------------------------  ;
; Small Delay                                            ;
; -----------------------------------------------------  ;
SDelay:                                                  ;
        stmfd  sp!,{r0-r11, r12, lr}                     ; Store registers
        mov    r2,0x100000                               ;
S_Delayloop:                                             ;
        subs   r2,r2, 1                                  ;
        bne    S_Delayloop                               ;
        ldmfd  sp!,{r0-r11, r12, pc}                     ; Restore registers and return
align 4                                                  ;
SetFB_X   dw 0                                           ;
SetFB_Y   dw 0                                           ;
SetFB_BPP dw 0                                           ;
align 4                                                  ;
ScrBuffer:                                               ; The off screen frame buffer       
This sets the screen mode you want and fills the screen with white pixels and than stops, by just looping.
Batteries not included, Some assembly required.

GeneraV
Posts: 31
Joined: Mon Feb 04, 2013 2:10 am

Re: Set screen resolution

Thu Mar 14, 2013 2:02 am

Thanks Dex for the source code, much appreciated. Tried it same result 1360x786. It fills the entire screen. Booted into risc os had the same screen resolution on boot but switched to 1920x1080 on entering the desktop but the tv didn't say it had done so :? Very strange indeed! Could it be a problem with the tv I wonder! Ah well..... Obviously the GPU is returning a pointer to the screen to display. I'll think I write something to the display that is beyond 1360 and see if is displayed or not. I'll let you know my results.

GeneraV
Posts: 31
Joined: Mon Feb 04, 2013 2:10 am

Re: Set screen resolution

Thu Mar 14, 2013 11:34 pm

Well this is my progress so far! Altered your code Dex to place a single black pixel at the x1500 and it was displayed :D so why my tv is giving those resolution figures is a little bit of a puzzel :? I am going to assume my code is correct and everthing is working ok :) So ,with that, I thank everybody for their help, and hope my code doesn't break any time soon ;)

Return to “Bare metal, Assembly language”