It has been a fun mini-adventure to make the SPI LCD display work nicely on RISCOS...
There is a third-party module available to do communications on RISCOS, called PiSPI, but it is very basic and it takes more than a second to send all the data for refreshing the screen once. This effort started because I wanted to progress to investigating using the DMA engine on the Raspberry Pi, which is why the variable
contains the data in a format ready to be sent via the DMA engine. In any case, there is a lot of RAM available on the Raspberry Pi.
system calls, which support creating sprites in many bit depths and sizes. It supports the 16bit format used by the display. Unfortunately, there is no call to rotate sprites and because the display is a 240x320 portrait display and I wanted to use it as if it was a 320x240 landscape display, I had to do that transformation for myself.
In spite of being "PIO" mode, performance is respectable.
Since this now works "good enough", I will proceed with other parts of my project and I may return to it when I need to get the DMA stuff working... Most likely because I'd like to find ways to reduce power consumption.
10 REM >DMA9341
20
30 spiclk%=4
40
50 SYS "OS_SWINumberFromString",,"OS_SpriteOp" TO spriteOp%
60 SYS "OS_SWINumberFromString",,"ColourTrans_SetGCOL" TO setGCOL%
70 SYS "OS_SWINumberFromString",,"ColourTrans_ReturnColourNumber" TO getColourNumber%
80
90 DIM vdurestore%(3)
100
110 DIM code% 4096
120 PRINT "Allocating scratchpad at ";~code%
130
140 REM 320 * 240 * 16bit + 44 sprite header + 16 area header = 1536460
150 DIM spritearea% 153660
160
170 REM 320 * 240 * 16bit * 32bit words = 614400
180 DIM dmabuffer% 614400
190
200 spritearea%!0=153660
210 spritearea%!4=0
220 spritearea%!8=16
230 spritearea%!12=16
240
250 PRINT "Initializing sprite area at ";~spritearea%
260 SYS spriteOp%,256+15,spritearea%,"lcd",0,320,240,&78a04001
270 spriteptr%=spritearea%+16
280
290 PRINT "Initializing sprite at ";~spriteptr%
300 SYS spriteOp%,512+62,spritearea%,spriteptr% TO sarsize%
310
320 DIM savearea% sarsize%
330 PRINT "Initializing savearea at ";~savearea%
340 savearea%!0=0
350
360 SYS "OS_Memory",13,&20200000,&100 TO ,,,gpio%
370 PRINT "GPIO mapped at ";~gpio%
380 SYS "OS_Memory",13,&20204000,&100 TO ,,,spi%
390 PRINT "SPI mapped at ";~spi%
400
410 PROCinitGPIO
420
430 DIM spiSendCode% 1024
440 FOR pass%=0 TO 2 STEP 2
450 P%=spiSendCode% : [ OPT pass%
460 .spiSend
470 SWI "OS_EnterOS"
480 ; SWI 256+65
490 LDR R3,gpiov
500 MOV R4,#1
510 MOV R2,R4,LSL #25
520 STR R2,[R3,#40]
530 MCR cp15,0,R3,c7,c10,5
540 :
550 LDR R3,spiv
560 LDR R2,[R3,#0]
570 AND R2,R2,#&0c
580 ORR R2,R2,#&6b0
590 STR R2,[R3,#0]
600 :
610 MCR cp15,0,R3,c7,c10,5
620 STR R0,[R3,#4]
630 :
640 .cmdwait
650 MCR cp15,0,R3,c7,c10,5
660 LDR R2,[R3,#0]
670 TST R2,#1<<16
680 BEQ cmdwait
690 ; SWI 256+66
700 TST R2,#1<<17
710 LDRNE R0,[R3,#4]
720 ;ORR R2,R2,#&30
730 ;STR R2,[R3,#0]
740 :
750 LDR R3,gpiov
760 MOV R4,#1
770 MOV R2,R4,LSL #25
780 STR R2,[R3,#28]
790 MCR cp15,0,R3,c7,c10,5
800 :
810 LDR R3,spiv
820 :
830 .isdone
840 MOV R0,R1
850 ADD R0,R0,#64
860 CMP R0,R5
870 BHI sendrem
880 :
890 ;SWI 256+67
900 LDR R0,[R1],#4
910 STR R0,[R3,#4]
920 LDR R0,[R1],#4
930 STR R0,[R3,#4]
940 LDR R0,[R1],#4
950 STR R0,[R3,#4]
960 LDR R0,[R1],#4
970 STR R0,[R3,#4]
980 :
990 LDR R0,[R1],#4
1000 STR R0,[R3,#4]
1010 LDR R0,[R1],#4
1020 STR R0,[R3,#4]
1030 LDR R0,[R1],#4
1040 STR R0,[R3,#4]
1050 LDR R0,[R1],#4
1060 STR R0,[R3,#4]
1070 :
1080 LDR R0,[R1],#4
1090 STR R0,[R3,#4]
1100 LDR R0,[R1],#4
1110 STR R0,[R3,#4]
1120 LDR R0,[R1],#4
1130 STR R0,[R3,#4]
1140 LDR R0,[R1],#4
1150 STR R0,[R3,#4]
1160 :
1170 LDR R0,[R1],#4
1180 STR R0,[R3,#4]
1190 LDR R0,[R1],#4
1200 STR R0,[R3,#4]
1210 LDR R0,[R1],#4
1220 STR R0,[R3,#4]
1230 LDR R0,[R1],#4
1240 STR R0,[R3,#4]
1250 :
1260 CMP R1,R5
1270 BEQ endsend
1280 :
1290 .bulk
1300 ; SWI 256+72
1310 MCR cp15,0,R3,c7,c10,5
1320 .busyloop
1330 LDR R2,[R3,#0]
1340 TST R2,#1<<16
1350 BNE isdone
1360 TST R2,#1<<19
1370 ;MCREQ cp15,0,R3,c7,c0,4 ;wait for interrupt
1380 BEQ busyloop
1390 :
1400 ; SWI 256+73
1410 MOV R0,R1
1420 ADD R0,R0,#48
1430 CMP R0,R5
1440 BHI sendrem
1450 :
1460 ; SWI 256+74
1470 LDR R2,[R3,#4]
1480 LDR R0,[R1],#4
1490 STR R0,[R3,#4]
1500 LDR R2,[R3,#4]
1510 LDR R0,[R1],#4
1520 STR R0,[R3,#4]
1530 LDR R2,[R3,#4]
1540 LDR R0,[R1],#4
1550 STR R0,[R3,#4]
1560 LDR R2,[R3,#4]
1570 LDR R0,[R1],#4
1580 STR R0,[R3,#4]
1590 :
1600 LDR R2,[R3,#4]
1610 LDR R0,[R1],#4
1620 STR R0,[R3,#4]
1630 LDR R2,[R3,#4]
1640 LDR R0,[R1],#4
1650 STR R0,[R3,#4]
1660 LDR R2,[R3,#4]
1670 LDR R0,[R1],#4
1680 STR R0,[R3,#4]
1690 LDR R2,[R3,#4]
1700 LDR R0,[R1],#4
1710 STR R0,[R3,#4]
1720 :
1730 LDR R2,[R3,#4]
1740 LDR R0,[R1],#4
1750 STR R0,[R3,#4]
1760 LDR R2,[R3,#4]
1770 LDR R0,[R1],#4
1780 STR R0,[R3,#4]
1790 LDR R2,[R3,#4]
1800 LDR R0,[R1],#4
1810 STR R0,[R3,#4]
1820 LDR R2,[R3,#4]
1830 LDR R0,[R1],#4
1840 STR R0,[R3,#4]
1850 :
1860 CMP R1,R5
1870 BNE bulk
1880 :
1890 .endsend
1900 ; SWI 256+69
1910 .endloop
1920 MCR CP15,0,R3,c7,c10,5
1930 LDR R2,[R3,#0]
1940 TST R2,#1<<17
1950 LDRNE R0,[R3,#4]
1960 TST R2,#1<<16
1970 BEQ endloop
1980 :
1990 ORR R2,R2,#&30
2000 BIC R2,R2,#&80
2010 STR R2,[R3,#0]
2020 :
2030 SWI "OS_LeaveOS"
2040 :
2050 MOV PC,R14
2060 :
2070 .sendrem
2080 ; SWI 256+68
2090 CMP R1,R5
2100 BEQ endsend
2110 LDR R0,[R1],#4
2120 STR R0,[R3,#4]
2130 BAL sendrem
2140 :
2150 .gpiov
2160 EQUD gpio%
2170 .spiv
2180 EQUD spi%
2190 .SPI_AND_MASK
2200 EQUD &0000000c
2210 .SPI_OR_MASK
2220 EQUD &000006b0
2230 :
2240
2250 .lineblt
2260 LDR R1,[R0],#4
2270 MOV R4,R1,LSR #8
2280 AND R3,R1,#&ff
2290 AND R4,R4,#&ff
2300 STR R4,[R2],#4
2310 STR R3,[R2],#-&784
2320 MOV R4,R1,LSR #24
2330 MOV R3,R1,LSR #16
2340 AND R4,R4,#&ff
2350 AND R3,R3,#&ff
2360 STR R4,[R2],#4
2370 STR R3,[R2],#-&784
2380 CMP R5,R2
2390 MOVHI PC,R14
2400 BAL lineblt
2410 :
2420 ] : NEXT pass%
2430
2440 PRINT "Resetting LCD display"
2450 PROClcdReset
2460 PRINT "Initializing LCD display"
2470 PROClcdSetup
2480 PRINT "Performing first update"
2490 start%=TIME:PROClcdUpdate:PRINT "Took ";(TIME-start%)/100;" seconds"
2500 REM PRINT "again"
2510 REM PROClcdUpdate
2520 REM END
2530 PRINT "Running PROCtest"
2540 PROCtest
2550
2560 END
2570
2580 DEF PROCspi(cmd%,addr%,end%)
2590 REM PRINT "PROCspi(&";~cmd%;",&";~addr%;",&";~end%;")"
2600 A%=cmd%:B%=addr%:F%=end%
2610 CALL spiSend
2620 ENDPROC
2630
2640 DEF PROClcdUpdate
2650 LOCAL y%
2660 A%=spriteptr%+44
2670 FOR y%=dmabuffer% TO dmabuffer%+&778 STEP 8
2680 C%=y%+&95880:F%=y%:A%=USR lineblt
2690 NEXT y%
2700 PROCspi(&2c,dmabuffer%,dmabuffer%+614400)
2710 ENDPROC
2720
2730 DEF PROCsetGCOL(rgb%)
2740 SYS setGCOL%,rgb%,,,0,3
2750 ENDPROC
2760
2770 DEF PROCsetColour(rgb%)
2780 LOCAL colour%
2790 SYS getColourNumber,rgb% TO colour%
2800 COLOUR colour%
2810 ENDPROC
2820
2830 DEF PROCtest2
2840 LOCAL x%,y%,p%
2850 p%=spriteptr%+44
2860 FOR y%=0 TO 239
2870 FOR x%=0 TO 319
2880 IF (x% AND &4)=(y% AND &4) THEN
2890 p%?0 = &ff
2900 p%?1 = &ff
2910 ELSE
2920 p%?0 = &00
2930 p%?1 = &00
2940 ENDIF
2950 p%=p%+2
2960 NEXT x%
2970 NEXT y%
2980 PROClcdUpdate
2990 ENDPROC
3000
3010 DEF PROCtest
3020 LOCAL start%,end%,c%
3030 PROCvduLcdSprite
3040
3050 PRINT "Hello World from RISCOS"
3060 start%=TIME:PROClcdUpdate:end%=TIME
3070 PRINT
3080
3090 PRINT "frame refresh takes ";(end%-start%)/100;" seconds"
3100
3110 FOR c%=0 TO 63
3120 COLOUR c%
3130 PRINT "*";
3140 NEXT c%
3150 PRINT:PRINT
3160
3170 PROCvduRestore
3180 PROClcdUpdate
3190 ENDPROC
3200
3210 DEF PROCvduLcdSprite
3220 IF vdurestore%(0) THEN
3230 ERR 6,"Cannot switch"
3240 ELSE
3250 SYS spriteOp%,60+512,spritearea%,spriteptr%,savearea% TO vdurestore%(0),vdurestore%(1),vdurestore%(2),vdurestore%(3)
3260 ENDIF
3270 ENDPROC
3280
3290 DEF PROCvduRestore
3300 IF vdurestore%(0) THEN
3310 SYS spriteOp%,vdurestore%(0),vdurestore%(1),vdurestore%(2),vdurestore%(3)
3320 vdurestore%(0)=0
3330 ELSE
3340 ERR 6,"Cannot restore"
3350 ENDIF
3360 ENDPROC
3370
3380 DEF PROCinitGPIO
3390 LOCAL pass%
3400 FOR pass%=0 TO 2 STEP 2
3410 P%=code% : [ OPT pass%
3420 .start
3430 SWI "OS_EnterOS"
3440 LDR R0, GPSEL0_OR_MASK
3450 LDR R2,[R1,#0]
3460 ORR R2,R2,R0
3470 LDR R0, GPSEL0_AND_MASK
3480 AND R2,R2,R0
3490 STR R2,[R1,#0]
3500 LDR R0,GPSEL1_OR_MASK
3510 LDR R2,[R1,#4]
3520 ORR R2,R2,R0
3530 LDR R0,GPSEL1_AND_MASK
3540 AND R2,R2,R0
3550 STR R2,[R1,#4]
3560 ;LDR R0,GPSEL2_OR_MASK
3570 ;LDR R2,[R1,#8]
3580 ;ORR R2,R2,R0
3590 ;LDR R0,GPSEL2_AND_MASK
3600 ;AND R2,R2,R0
3610 ;STR R2,[R1,#8]
3620 MOV R0,#%11<<6
3630 STR R0,[R1,#&1c]
3640 MOV R0,#%111<<9
3650 STR R0,[R1,#&28]
3660 MOV R0,#&3c
3670 STR R0,[R3,#0]
3680 MOV R0,#spiclk%
3690 STR R0,[R3,#&8]
3700 SWI "OS_LeaveOS"
3710 MOV PC,R14
3720 :
3730 .GPSEL0_OR_MASK
3740 EQUD &24800000
3750 :
3760 .GPSEL0_AND_MASK
3770 EQUD &249fffff
3780 :
3790 .GPSEL1_OR_MASK
3800 EQUD &00000024
3810 :
3820 .GPSEL1_AND_MASK
3830 EQUD &2fffffe4
3840 :
3850 .GPSEL2_OR_MASK
3860 EQUD &00024000
3870 :
3880 .GPSEL2_AND_MASK
3890 EQUD &fffc0fff
3900 ] : NEXT pass%
3910 B%=gpio%:D%=spi%
3920 CALL start
3930 SYS "GPIO_WriteMode",24,1
3940 SYS "GPIO_WriteMode",25,1
3950 ENDPROC
3960
3970 DEF PROClcdSetup
3980 LOCAL DATA
3990 RESTORE +0
4000 DATA &1ef,&03,&80,&02
4010 DATA &1cf,&00,&c1,&30
4020 DATA &1ed,&64,&03,&12,&81
4030 DATA &1e8,&85,&00,&78
4040 DATA &1cb,&39,&2c,&00,&34,&02
4050 DATA &1f7,&20
4060 DATA &1ea,&00,&00
4070 DATA &1c0,&23
4080 DATA &1c1,&10
4090 DATA &1c5,&3e,&28
4100 DATA &1c7,&86
4110 DATA &136,&48
4120 DATA &13a,&55
4130 DATA &1b1,&00,&18
4140 DATA &1b6,&08,&82,&27
4150 DATA &1f2,&00
4160 DATA &126,&01
4170 DATA &1e0,&0f,&31,&2b,&0c,&0e,&08,&4e,&f1,&37,&07,&10,&03,&0e,&09,&00
4180 DATA &1e1,&00,&0e,&14,&03,&11,&07,&31,&c1,&48,&08,&0f,&0c,&31,&36,&0f
4190 DATA &111
4200 DATA -1
4210 PROClcdSendInitData
4220 PROCsleep(0.120)
4230 PROCspi(&29,code%,code%)
4240 RESTORE DATA
4250 ENDPROC :
4260 :
4270 DEF PROClcdSendInitData
4280 LOCAL ptr%
4290 ptr%=code%
4300 READ !ptr%
4310 WHILE -1<!ptr%
4320 !ptr%=&ff AND !ptr%
4330 ptr%=ptr%+4
4340 READ !ptr%
4350 WHILE (&100 AND !ptr%)=0
4360 ptr%=ptr%+4
4370 READ !ptr%
4380 ENDWHILE
4390 PROCspi(!code%,code%+4,ptr%)
4400 !code%=!ptr%
4410 ptr%=code%
4420 ENDWHILE
4430 ENDPROC
4440 :
4450 DEF PROCsleep(d)
4460 ptr%=d*100+TIME:REPEAT:WAIT:UNTIL TIME>=ptr%
4470 ENDPROC
4480 :
4490 DEF PROClcdReset
4500 SYS "GPIO_WriteData",24,1
4510 PROCsleep(0.005)
4520 SYS "GPIO_WriteData",24,0
4530 PROCsleep(0.020)
4540 SYS "GPIO_WriteData",24,1
4550 PROCsleep(0.150)
4560 ENDPROC