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
dmabuffer%
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.
What is very convenient on RISCOS is the
OS_SpriteOp
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.
A few notes about this implementation:
- GPIO25 is attached to the command/data pin of the display.
- GPIO24 is attached to the reset pin of the display.
- The SPI pins are attached as one would expect.
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