Home
JAQForum Ver 20.06
Log In or Join  
Active Topics
Local Time 00:07 30 Apr 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Micromite MK2 graphic library and drivers

     Page 1 of 2    
Author Message
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 8584
Posted: 06:07am 16 Nov 2014
Copy link to clipboard 
Print this post

I've completed a fully working version of the graphics library including drivers supporting both the SSSD1306 OLED and the Nokia 5110 displays. I'm using cFunctions to optimise some of the critical code areas and I think the speed achieved now is fully usable for most applications. Obviously more of the basic could be converted into cFunctions to speed it up further and I haven't yet tackled accessing the PIC device registers from C. The downside of cFunctions is that errors typically result in a processor reset making debugging much harder than in basic alone.



I'll attach the code and Cfunction source below but first I wanted to thank Geoff (what you have achieved is extraordinary!),Jim Hiley (mm-edit) and Peter Carnegie (cFuncgen and the tutorial) for creating a great development environment for embedded computing. I've used a fair range of the options out there, picaxe, arduino, Texas Instruments Tiva, etc. but the micromite mk2 together with the cfunction capability is just superb.

The development process I've used for the code is to have mm-edit, notepad++, mplabx, and cFuncgen all open on the computer. The basic code development is done in mm-edit, cfunctions are developed in mplabx, once compiled press the refresh button on cfuncgen and it reads in the new elf file and then press the make cfunction button. Notepad++ immediately recognises that the cfunction basic file has changed and reloads it, then it can be copied and pasted into mm-edit. Using this process a change to a cfunction and retest on the micromite can be done in less than a minute. If cFuncgen doesn't work for you, re-install XC32 and make sure you tick the "add-to-path" box.

There is one common issue with the SSD1306 OLED boards. Many of the cheap boards (even the 4 pin ones) say they are i2c but don't work properly. They do not send the required "ACK" when receiving data. The Arduino community have solved this by producing an i2c library that works without the "ACK" but this is a poor solution. There is however an easy hardware fix. A blob of solder between pins 19 and 20 on the cable from the display where is connects to its PCB connects DIN and DOUT which is one of the requirements for the SSD1306 controller to work properly in i2c mode - check your display and mod if required!!!

My code is a port from the Adafruit graphics library - thanks to them for making their code available. It uses two 128 element 64-bit integer arrays "screen" and "displayed" to map the actual display. The graphics routines modify the "screen" array in the micromite memory and then the "refresh" command writes to the actual display and updates the "displayed" array. In this way the "refresh" command can compare the arrays and optimise what it need to write. I'm using a cFunction to do this compare and this function not only returns the x,y coordinates of the screen element to be updated but also whether a cursor positioning instruction is needed (quite pleased with this )

There are only 6 display specific subroutines required to integrate another type of display: initialise, sendcommand, sendchar, refresh, clearscreen, and cursor position. Both the Nokia5110 and the SSD1306 take an 8-bit data input and write it as a vertical block of pixels within a display row. The Nokia is 48 pixels high and 84 wide so there are 6 (48/8) rows of 84 data bytes required to write the full screen. The SSD1306 has 8 rows with 128 positions on each.

The text routines in the library allow the text to be position in any orientation at any position on the display unconstrained by the row structure. A faster text mechanism could be produced that only wrote within a single row.

I've tested this fairly thoroughly but please let me have details of any bugs I've missed. During the course of this development I've found only one trivial problem in the MK2 code despite it being beta and one out-and-out bug in the XC32 C compiler (shifts on long long variables don't cross the "long" boundary)

The routines support display rotation (separate from text rotation), however, the optimisation of the text functions when the character size is greater than normal do not support a rotated display so text write will be slower if the screen orientation is not "normal". This can be solved but is yet more coding and one has to draw a line somewhere!

If this library is useful I'm happy to act as a central clearing station for any additional cFunctions upgrades or any other additional functions.

Best Regards

Peter

NB Just noticed the board software had corrupted the C file - something to do with square brackets so I've attached it as a zip. Any problems with the basic let me know and I'll do the same


' Monochrome Port of Adafruit graphics library with drivers for i2c ssd1306 display
'
' assumes a graphics display where top left is point 0,0
'
'sub setRotation(x) 'sets screen rotation: 0=normal, 1=invert, 2=rotate right, 3-rotate left
'sub drawCircle(x0,y0,r) 'x,y coordinates of centre, radius
'sub fillCircle(x0, y0, r) 'x,y coordinates of centre, radius
'sub drawTriangle(x0, y0, x1, y1, x2, y2) 'three coordinate pairs
'sub fillTriangle (x0, y0, x1, y1, x2, y2) 'three coordinate pairs
'sub drawChar(x, y, c, fg$, bg$, size, orientation) 'x,y coordinates of top left of first character, ascii character, size, orientation
'sub printstring(xx0,yy0,text$,fg$,bg$,size,orientation) 'x,y coordinates of top left of first character, text string, size, orientation
'sub drawLine(xx0,yy0,xx1,yy1)' x,y of start line, x,y of end line
'sub drawFastHLine(x, y,w)'draw horizontal line: x,y coordinates of left of line, width
'sub drawFastVLine(x, y,h)'draw horizontal line: x,y coordinates of top of line, height
'sub drawRect(x,y,w,h) 'x,y coordinate of top left, width, height
'sub fillRect(x, y, w, h)'x,y coordinate of top left, width, height
'sub drawRoundRect(x, y, w, h, r) 'x,y coordinates of top left, width, height, radius of corner
'sub fillRoundRect(x, y, w,h, r) 'x,y coordinates of top left, width, height, radius of corner
'
' These routines now just update the memory image of the display
' Use the refresh command to write to the display as required
'
'CFunctions
'unsigned long long fastfillrect(unsigned int *onoff,unsigned int *x,unsigned int *y, unsigned int *width,unsigned int *height,unsigned int *numcols, unsigned int *numrows,unsigned long long screen[]){
'unsigned long long getnextupdate(unsigned int *outchar,unsigned int *col, unsigned int *row,unsigned int *maxcols,unsigned int *maxrows, unsigned long long screen[], unsigned long long displayed[]){
'unsigned long long drawPixel(unsigned int *onoff, unsigned int *x, unsigned int *y, unsigned int *rotation, unsigned int *width, unsigned int *height, unsigned int *rot_width, unsigned int *rot_height, unsigned long long p_array[]){
'long long charload(long long loadarray[]) {
'
cpu 48
OPTION EXPLICIT
OPTION DEFAULT INTEGER
const normal=0
const invert=1
const rotate_right=2
const rotate_left=3
const ON=1
const OFF=0
const SSD1306=0 'display code for SSD1306 i2c display
const NOKIA5110=1 ' display code for NOKIA5110 SPI display
const DisplayInUse=NOKIA5110 'set the display to be used
'
' SSD1306 Display specific constants
const SSD1306_width=128
const SSD1306_height=64
const SSD1306_NUM_ROWS = SSD1306_height/8 'memory is arranged as rows 8 bits high
const SSD1306_i2caddr=&H3C
const SSD1306_SETCONTRAST =&H81
const SSD1306_DISPLAYALLON_RESUME =&HA4
const SSD1306_DISPLAYALLON =&HA5
const SSD1306_NORMALDISPLAY =&HA6
const SSD1306_INVERTDISPLAY =&HA7
const SSD1306_DISPLAYOFF =&HAE
const SSD1306_DISPLAYON =&HAF
const SSD1306_SETDISPLAYOFFSET =&HD3
const SSD1306_SETCOMPINS =&HDA
const SSD1306_SETVCOMDETECT =&HDB
const SSD1306_SETDISPLAYCLOCKDIV =&HD5
const SSD1306_SETPRECHARGE =&HD9
const SSD1306_SETMULTIPLEX =&HA8
const SSD1306_SETLOWCOLUMN =&H00
const SSD1306_SETHIGHCOLUMN =&H10
const SSD1306_SETSTARTLINE =&H40
const SSD1306_MEMORYMODE =&H20
const SSD1306_COLUMNADDR =&H21
const SSD1306_PAGEADDR =&H22
const SSD1306_COMSCANINC =&HC0
const SSD1306_COMSCANDEC =&HC8
const SSD1306_SEGREMAP =&HA0
const SSD1306_CHARGEPUMP =&H8D
const SSD1306_EXTERNALVCC =&H1
const SSD1306_SWITCHCAPVCC =&H2'
'
' Nokia 5110 Display specific constants
'
const NOKIA5110_WIDTH=84
const NOKIA5110_HEIGHT=48
const NOKIA5110_NUM_ROWS = NOKIA5110_Height/8
const NOKIA5110_EXTENDED_COMMAND = &H21
const NOKIA5110_BASIC_COMMAND = &H20
const NOKIA5110_TEMP_COEFFICIENT = &H05
const NOKIA5110_BIAS = &H14
const NOKIA5110_BLANK = &H08
const NOKIA5110_ALL_ON = &H09
const NOKIA5110_D_NORMAL = &H0C
const NOKIA5110_D_INVERSE = &H0D
const NOKIA5110_xcursor=&H80
const NOKIA5110_ycursor=&H40
const NOKIA5110_CONTRAST = &HB0 'adjust for individual display
'
' pin assignments for Nokia 5110
'
const NOKIA5110_RST=24
const NOKIA5110_CE=23
const NOKIA5110_DC=15
const NOKIA5110_Datain=3
const NOKIA5110_CLK=25
const NOKIA5110_VCC=7
'
'
dim width,height,num_rows,i2caddr
dim c(255)
dim screen(128),displayed(128) 'set up arrays for screen map to mimic display
dim i,j,k,char
dim rotation
dim rot_width,rot_height
'
init:
print "Starting initialisation"
if DisplayInUse=SSD1306 then
print "Using ssd1306"
width=SSD1306_width
height=SSD1306_height
num_rows=SSD1306_num_rows
i2caddr=SSD1306_i2caddr
initSSD1306display 'initialise the display
endif
if DisplayInUse=NOKIA5110 then
print "Using NOKIA5110"
width=NOKIA5110_width
height=NOKIA5110_height
num_rows=NOKIA5110_num_rows
initNOKIA5110display 'initialise the display
endif
i=charload(c())
setrotation(normal)
print "starting main"
'
Main:
if DisplayInUse=ssd1306 then ssd1306_clearscreen
if DisplayInUse=NOKIA5110 then NOKIA5110_clearscreen
fillcircle(width/2,height/2,height/2-6)
drawcircle(width/2,height/2,height/2-4)

if DisplayInUse=ssd1306 then ssd1306_refresh
if DisplayInUse=NOKIA5110 then NOKIA5110_refresh
for j=1 to 4 'size of character
for i=0 to 254 'character code
drawchar(0,0,i,j,normal)
drawchar(width-1,height-1,i,j,invert)
drawchar(width-1,0,i,j,rotate_right)
drawchar(0,height-1,i,j,rotate_left)
if DisplayInUse=ssd1306 then ssd1306_refresh
if DisplayInUse=NOKIA5110 then NOKIA5110_refresh
next i
next j
goto main
end
'
'*********************************************************** ********************************
'
' SSD1306 Display specific routines
'
sub initSSD1306display 'i2c oled
I2C OPEN 400,1000
ssd1306_command(SSD1306_DISPLAYOFF)' &HAE
ssd1306_command(SSD1306_SETDISPLAYCLOCKDIV)'&HD5
ssd1306_command(&H80)'the suggested ratio &H80
ssd1306_command(SSD1306_SETMULTIPLEX)'&HA8
ssd1306_command(&H3F)'
ssd1306_command(SSD1306_SETDISPLAYOFFSET)'&HD3
ssd1306_command(&H0)'no offset
ssd1306_command(SSD1306_SETSTARTLINE )'line #0
ssd1306_command(SSD1306_CHARGEPUMP)'&H8D
ssd1306_command(&H14)
ssd1306_command(SSD1306_MEMORYMODE)' &H20
ssd1306_command(&H00)'&H0 act like ks0108
ssd1306_command(SSD1306_SEGREMAP OR 1);
ssd1306_command(SSD1306_COMSCANDEC);
ssd1306_command(SSD1306_SETCOMPINS)' &HDA
ssd1306_command(&H12)
ssd1306_command(SSD1306_SETCONTRAST)'&H81
ssd1306_command(&HCF)
ssd1306_command(SSD1306_SETPRECHARGE)'&Hd9
ssd1306_command(&HF1)
ssd1306_command(SSD1306_SETVCOMDETECT)'&HDB
ssd1306_command(&H40)
ssd1306_command(SSD1306_DISPLAYALLON_RESUME)'&HA4
ssd1306_command(SSD1306_NORMALDISPLAY)'&HA6
ssd1306_command(SSD1306_DISPLAYON)
'
ssd1306_clearscreen
end sub
'
Sub ssd1306_Command(command)
I2C WRITE i2caddr,0,2,&H00,command
end sub
'
'
sub ssd1306_SendData(Dchar)
I2C WRITE i2caddr,0,2,&H40,Dchar
end sub
'
sub SSD1306_refresh
ssd1306_cursor(0,0)
local rows=0
local cols=0
local outchar
local retstatus
do
retstatus=getnextupdate(outchar,cols,rows,width,num_rows,scr een(),displayed())
if retstatus=0 then ssd1306_senddata(outchar)
if retstatus=1 then
ssd1306_cursor(cols,rows)
ssd1306_senddata(outchar)
endif
loop while retstatus<>2
end sub
'
Sub SSD1306_ClearScreen
local i,j
for i=0 to num_rows-1
ssd1306_cursor(0,i)
for j=0 to width\16 -1
I2C WRITE i2caddr,0,17,&H40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
next j
next i
for i=0 to width-1
screen(i)=0
displayed(i)=0
next i
end sub
'
sub SSD1306_Cursor(x,y)
ssd1306_command(&HB0 + y) //set page address
ssd1306_command(&H10+(x>>4 and &H0F)) //set high col address
ssd1306_command(&H00+(x AND &H0f)) //set low col address
end sub
'
'*********************************************************** ********************************
'
' Nokia5110 Display specific routines
'
sub initNOKIA5110display
setpin NOKIA5110_RST, dout
SETPIN NOKIA5110_CE, DOUT
SETPIN NOKIA5110_DC, DOUT
SETPIN NOKIA5110_VCC, DOUT
spi open 6000000,3,8
PIN(NOKIA5110_VCC)=0 'turn off display power
pause 500
pin(NOKIA5110_RST)=1 'set RESET high
PIN(NOKIA5110_VCC)=1 'Turn on the power
PIN(NOKIA5110_RST)=0
PIN(NOKIA5110_RST)=1 'reset the display
NOKIA5110_SendCommand(NOKIA5110_EXTENDED_COMMAND)
NOKIA5110_SendCommand(NOKIA5110_TEMP_COEFFICIENT)
NOKIA5110_SendCommand(NOKIA5110_BIAS)
NOKIA5110_SendCommand(NOKIA5110_BASIC_COMMAND)
NOKIA5110_SendCommand(NOKIA5110_D_NORMAL)
NOKIA5110_ClearScreen
NOKIA5110_SendCommand(NOKIA5110_EXTENDED_COMMAND)
NOKIA5110_SendCommand(NOKIA5110_CONTRAST OR &H80)
NOKIA5110_SendCommand(NOKIA5110_BASIC_COMMAND)
end sub
'
sub NOKIA5110_refresh
local rows=0
local cols=0
local outchar
local retstatus
NOKIA5110_cursor(0,0)
do
retstatus=getnextupdate(outchar,cols,rows,width,num_rows,scr een(),displayed())
if retstatus=0 then NOKIA5110_senddata(outchar)
if retstatus=1 then
NOKIA5110_cursor(cols,rows)
NOKIA5110_senddata(outchar)
endif
loop while retstatus<>2
end sub
'
Sub NOKIA5110_SendCommand(command)
pin(NOKIA5110_DC)=0 ' Send this byte as a command
PIN(NOKIA5110_CE)=0
local i=spi(command)
PIN(NOKIA5110_CE)=1
end sub
'
sub NOKIA5110_SendData(Dchar)
PIN(NOKIA5110_DC)=1 ' Send this byte as data
PIN(NOKIA5110_CE)=0
local i=spi(Dchar)
PIN(NOKIA5110_CE)=1
end sub
'
Sub NOKIA5110_ClearScreen
local i,j
for i=0 to num_rows-1
screen(i)=0
displayed(i)=0
for j=0 to width-1
NOKIA5110_SendData(0)
next j
next i
end sub
'
sub NOKIA5110_Cursor(x,y)
NOKIA5110_SendCommand(x or NOKIA5110_xcursor)
NOKIA5110_SendCommand(y OR NOKIA5110_ycursor)
end sub
'
'*********************************************************** ********************************
'
' Generic drawing routines
'
sub drawCircle(x0,y0,r) 'x,y coordinates of centre, radius
local f=1-r
local ddF_x=1
local ddF_y=-2 * r
local x=0
local y=r
LOCAL dp=drawpixel(ON,x0 , y0+r,rotation,width,height,rot_width,rot_height,screen())
dp=drawpixel(ON,x0 , y0-r,rotation,width,height,rot_width,rot_height,screen())
dp=drawpixel(ON,x0+r, y0 ,rotation,width,height,rot_width,rot_height,screen())
dp=drawpixel(ON,x0-r, y0 ,rotation,width,height,rot_width,rot_height,screen())
do while (x<y)
if f >= 0 then
y=y-1
ddF_y = ddF_y+2
f = f+ddF_y
endif
x=x+1
ddF_x = ddF_x+2
f = f+ ddF_x

dp=drawpixel(ON,x0 + x, y0 + y,rotation,width,height,rot_width,rot_height,screen())
dp=drawpixel(ON,x0 - x, y0 + y,rotation,width,height,rot_width,rot_height,screen())
dp=drawpixel(ON,x0 + x, y0 - y,rotation,width,height,rot_width,rot_height,screen())
dp=drawpixel(ON,x0 - x, y0 - y,rotation,width,height,rot_width,rot_height,screen())
dp=drawpixel(ON,x0 + y, y0 + x,rotation,width,height,rot_width,rot_height,screen())
dp=drawpixel(ON,x0 - y, y0 + x,rotation,width,height,rot_width,rot_height,screen())
dp=drawpixel(ON,x0 + y, y0 - x,rotation,width,height,rot_width,rot_height,screen())
dp=drawpixel(ON,x0 - y, y0 - x,rotation,width,height,rot_width,rot_height,screen())
loop
end sub
'
sub drawTriangle(x0, y0, x1, y1, x2, y2) 'three coordinate pairs
drawLine(x0, y0, x1, y1)
drawLine(x1, y1, x2, y2)
drawLine(x2, y2, x0, y0)
end sub
'
sub fillTriangle (x0, y0, x1, y1, x2, y2) 'three coordinate pairs
local a, b, y, last
if (y0 > y1) then
swap(y0, y1)
swap(x0, x1)
endif
if (y1 > y2) then
swap(y2, y1)
swap(x2, x1)
endif
if (y0 > y1) then
swap(y0, y1)
swap(x0, x1)
endif
if(y0 = y2) then ' Handle awkward all-on-same-line case as its own thing
a = x0
b = x0
if(x1 < a) then
a = x1
else
if(x1 > b) then b = x1
endif
if(x2 < a) then
a = x2
else
if(x2 > b) then b = x2
endif
drawFastHLine(a, y0, b-a+1)
exit sub
endif
local dx01=x1 - x0
local dy01=y1 - y0
local dx02=x2 - x0
local dy02=y2 - y0
local dx12=x2 - x1
local dy12=y2 - y1
local sa = 0
local sb = 0
if(y1 = y2) then
last = y1 'Include y1 scanline
else
last = y1-1 ' Skip it
endif
for y=y0 to last
a = x0 + sa / dy01
b = x0 + sb / dy02
sa = sa + dx01
sb = sb + dx02
a = x0 + (x1 - x0) * (y - y0) / (y1 - y0)
b = x0 + (x2 - x0) * (y - y0) / (y2 - y0)
if(a > b) then swap(a,b)
drawFastHLine(a, y, b-a+1)
next y
sa = dx12 * (y - y1)
sb = dx02 * (y - y0)
do while y<=y2
a = x1 + sa / dy12
b = x0 + sb / dy02
sa = sa+dx12
sb = sb+dx02
a = x1 + (x2 - x1) * (y - y1) / (y2 - y1)
b = x0 + (x2 - x0) * (y - y0) / (y2 - y0)
if(a > b) then swap(a,b)
drawFastHLine(a, y, b-a+1)
y=y+1
loop
end sub
'
sub printstring(xx0,yy0,text$,size,orientation) 'x,y coordinates of top left of first character, text string, size, orientation
local i,c
local x = xx0
local y = yy0
for i=1 to len(text$)
c=asc(mid$(text$,i,1))
drawchar(x,y,c,size,orientation)
on orientation+1 goto pnormal,pinvert,protateright,protateleft
pnormal:
x=x+(6*size)
goto pcontinue
pinvert:
x=x-(6*size)
goto pcontinue
protateright:
y=y+(6*size)
goto pcontinue
protateleft:
y=y-(6*size)
pcontinue:
next i
end sub
'
sub drawLine(xx0,yy0,xx1,yy1) ' x,y of start line, x,y of end line
local dx, dy
local x0=xx0
local y0=yy0
local x1=xx1
local y1=yy1
local err,ystep
local steep = (abs(y1 - y0)) > (abs(x1 - x0))
if (steep) then
swap(x0, y0)
swap(x1, y1)
endif
if (x0 > x1) then
swap(x0, x1)
swap(y0, y1)
endif
dx = x1 - x0
dy = abs(y1 - y0)
err = dx / 2
if y0 < y1 then
ystep = 1
else
ystep = -1
endif
do while x0<=x1
if (steep) then
LOCAL dp=drawpixel(ON,y0, x0,rotation,width,height,rot_width,rot_height,screen())
else
dp=drawpixel(ON,x0, y0,rotation,width,height,rot_width,rot_height,screen())
endif
err = err- dy
if err < 0) then
y0 = y0+ ystep
err = err+ dx
endif
x0=x0+1
loop
end sub
'
sub swap a,b
local t
t=b
b=a
a=t
end sub
'
sub drawRect(x,y,w,h) 'x,y coordinate of top left, width, height
local a
drawFastHLine(x, y, w)
a=y+h-1
drawFastHLine(x, a, w)
drawFastVLine(x, y, h)
a=x+w-1
drawFastVLine(a, y, h)
end sub
'
sub drawFastVLine(x, y,h) 'draw horizontal line: x,y coordinates of top of line, height
LOCAL i,dp
for i=y to y+h-1
dp=drawpixel(ON,x, i,rotation,width,height,rot_width,rot_height,screen())
next i
end sub
'
sub clearFastVLine(x, y,h) 'draw horizontal line: x,y coordinates of top of line, height
LOCAL i,dp
for i=y to y+h-1
dp=drawpixel(OFF,x, i,rotation,width,height,rot_width,rot_height,screen())
next i
end sub
'
sub drawFastHLine(x, y,w) 'draw horizontal line: x,y coordinates of left of line, width
local i,dp
for i=x to x+w-1
dp=drawpixel(ON,i, y,rotation,width,height,rot_width,rot_height,screen())
next i
end sub
'
sub fillRect(x, y, w, h) 'x,y coordinate of top left, width, height
local i
for i=x to x+w-1
drawFastVLine(i, y, h)
next i
end sub
'
sub clearRect(x, y, w, h) 'x,y coordinate of top left, width, height
local i
for i=x to x+w-1
clearFastVLine(i, y, h)
next i
end sub
'
sub drawChar(xx, yy, ch, size, orientation) 'x,y coordinates of top left of first character, ascii character, size, orientation
local i,j,x,y,dp,addr,character
x=xx
y=yy
character=c(ch) 'loads the character
on orientation+1 goto dnormal,dinvert,drotateright,drotateleft
dnormal:
for i=0 to 5
for j = 0 to 7
if (character >> (i*8+j)) and 1 then
if (size = 1) then
dp=drawpixel(ON,x+5-i, y+j,rotation,width,height,rot_width,rot_height,screen())
else
if rotation then
fillrect(x+(5-i)*size, y+(j*size), size, size)
else
dp=fastfillrect(ON,x+(5-i)*size, y+(j*size), size, size,rot_width,rot_height,screen())
endif
endif
else
if (size = 1) then
dp=drawpixel(OFF,x+5-i, y+j,rotation,width,height,rot_width,rot_height,screen())
else
if rotation then
clearrect(x+(5-i)*size, y+(j*size), size, size)
else
dp=fastfillrect(OFF,x+(5-i)*size, y+(j*size), size, size,rot_width,rot_height,screen())
endif
endif
endif
next j
next i
exit sub
'
dinvert:
for i=0 to 5 'step down the lines
for j = 0 to 7
if (character >> (8*(5-i)+7-j)) and 1 then
if (size = 1) then
dp=drawpixel(ON,x-i, y+j-7,rotation,width,height,rot_width,rot_height,screen())
else
if rotation then
fillrect(x-size+1-(i*size), y-size+1+((j-7)*size), size, size)
else
dp=fastfillrect(ON,x-size+1-(i*size), y-size+1+((j-7)*size), size, size,rot_width,rot_height,screen())
endif
endif
else
if (size = 1) then
dp=drawpixel(OFF,x-i, y+j-7,rotation,width,height,rot_width,rot_height,screen())
else
if rotation then
clearrect(x-size+1-(i*size), y-size+1+((j-7)*size), size, size)
else
dp=fastfillrect(OFF,x-size+1-(i*size), y-size+1+((j-7)*size), size, size,rot_width,rot_height,screen())
endif
endif
endif
next j
next i
exit sub
'
drotateright:
for i=0 to 7 'step across the rows
for j = 0 to 5
if (character >> ((5-j)*8 + i)) and 1 then
if (size = 1) then
dp=drawpixel(ON,x-i, y+j,rotation,width,height,rot_width,rot_height,screen())
else
if rotation then
fillrect(x-size+1-i*size, y+(j)*size, size, size)
else
dp=fastfillrect(ON,x-size+1-i*size, y+(j)*size, size, size,rot_width,rot_height,screen())
endif
endif
else
if (size = 1) then
dp=drawpixel(OFF,x-i, y+j,rotation,width,height,rot_width,rot_height,screen())
else
if rotation then
clearrect(x-size+1-i*size, y+(j)*size, size, size)
else
dp=fastfillrect(OFF,x-size+1-i*size, y+(j)*size, size, size,rot_width,rot_height,screen())
endif
endif
endif
next j
next i
exit sub
drotateleft:
for i=0 to 7 'step across the rows
for j = 0 to 5
' if bits(5-j,i) then
if (character >> (8*j+7-i)) and 1 then
if (size = 1) then
dp=drawpixel(ON,x-i+7, y+j-5,rotation,width,height,rot_width,rot_height,screen())
else
dp=fastfillrect(ON,x-i*size+7*size+1, y+j*size-6*size+1, size, size,rot_width,rot_height,screen())
if rotation then
fillrect(x-i*size+7*size+1, y+j*size-6*size+1, size, size)
else
dp=fastfillrect(ON,x-i*size+7*size+1, y+j*size-6*size+1, size, size,rot_width,rot_height,screen())
endif
endif
else
if (size = 1) then
dp=drawpixel(OFF,x-i+7, y+j-5,rotation,width,height,rot_width,rot_height,screen())
else
if rotation then
clearrect(x-i*size+7*size+1, y+j*size-6*size+1, size, size)
else
dp=fastfillrect(OFF,x-i*size+7*size+1, y+j*size-6*size+1, size, size,rot_width,rot_height,screen())
endif
endif
endif
next j
next i
end sub
'
sub fillscreen 'fill colour
fillrect(0,0,rot_width,rot_height)
end sub
'
sub fillCircle(x0, y0, r) 'x,y coordinates of centre, radius
drawFastVLine(x0, y0-r, 2*r+1);
fillCircleHelper(x0, y0, r, 3, 0);
end sub
'
sub drawRoundRect(x, y, w, h, r) 'x,y coordinates of top left, width, height, radius of corner
drawFastHLine(x+r , y , w-2*r) ' Top
drawFastHLine(x+r , y+h-1, w-2*r) 'Bottom
drawFastVLine(x , y+r , h-2*r) 'Left
drawFastVLine(x+w-1, y+r , h-2*r) 'Right
drawCircleHelper(x+r , y+r , r, 1)
drawCircleHelper(x+w-r-1, y+r , r, 2)
drawCircleHelper(x+w-r-1, y+h-r-1, r, 4)
drawCircleHelper(x+r , y+h-r-1, r, 8)
end sub
'
sub drawCircleHelper( x0, y0,r,cornername)
local f = 1 - r
local ddF_x = 1
local ddF_y = -2 * r
local x = 0
local y = r

do while (x<y)
if (f >= 0) then
y=y-1
ddF_y = ddF_y+ 2
f = f+ddF_y
endif
x=x+1
ddF_x =ddF_x+ 2
f = f+ddF_x
if (cornername and 4) then
LOCAL dp=drawpixel(ON,x0 + x, y0 + y,rotation,width,height,rot_width,rot_height,screen())
dp=drawpixel(ON,x0 + y, y0 + x,rotation,width,height,rot_width,rot_height,screen())
endif
if (cornername and 2) then
dp=drawpixel(ON,x0 + x, y0 - y,rotation,width,height,rot_width,rot_height,screen())
dp=drawpixel(ON,x0 + y, y0 - x,rotation,width,height,rot_width,rot_height,screen())
endif
if (cornername and 8) then
dp=drawpixel(ON,x0 - y, y0 + x,rotation,width,height,rot_width,rot_height,screen())
dp=drawpixel(ON,x0 - x, y0 + y,rotation,width,height,rot_width,rot_height,screen())
endif
if (cornername and 1) then
dp=drawpixel(ON,x0 - y, y0 - x,rotation,width,height,rot_width,rot_height,screen())
dp=drawpixel(ON,x0 - x, y0 - y,rotation,width,height,rot_width,rot_height,screen())
endif
loop
end sub
'
sub fillCircleHelper(x0, y0, r,cornername, delta)

local f = 1 - r
local ddF_x = 1
local ddF_y = -2 * r
local x = 0
local y = r

do while x<y
if f >= 0 then
y=y-1
ddF_y =ddF_y+ 2
f = f+ddF_y
endif
x=x+1
ddF_x = ddF_x+2
f = f+ddF_x

if (cornername and 1) then
drawFastVLine(x0+x, y0-y, 2*y+1+delta)
drawFastVLine(x0+y, y0-x, 2*x+1+delta)
endif
if (cornername and 2) then
drawFastVLine(x0-x, y0-y, 2*y+1+delta)
drawFastVLine(x0-y, y0-x, 2*x+1+delta)
endif
loop
end sub
'
sub fillRoundRect(x, y, w,h, r) 'x,y coordinates of top left, width, height, radius of corner
fillRect(x+r, y, w-2*r, h)
fillCircleHelper(x+w-r-1, y+r, r, 1, h-2*r-1)
fillCircleHelper(x+r , y+r, r, 2, h-2*r-1)
end sub
'
sub setRotation(x) 'sets screen rotation: 0=normal, 1=invert, 2=rotate right, 3-rotate left
rotation = (x and 3)
if rotation >=2 then
rot_width = width
rot_height = height
else
rot_width=width
rot_height=height
endif

end sub
'
'*********************************************************** ********************************
'
' CFunctions
'
CFunction charload
00000000
00001021 00001821 ac820000 ac830004 3c024f5b 34423e00 24033e5b ac820008
ac83000c 3c024f6b 34423e00 24033e6b ac820010 ac830014 3c027c3e 34421c00
24031c3e ac820018 ac83001c 3c027e3c 34421800 2403183c ac820020 ac830024
3c027d57 34421c00 24031c57 ac820028 ac83002c 3c027f5e 34421c00 24031c5e
ac820030 ac830034 3c023c18 24030018 ac820038 ac83003c 3c02c3e7 3442ff00
3403ffe7 ac820040 ac830044 3c022418 24030018 ac820048 ac83004c 3c02dbe7
3442ff00 3403ffe7 ac820050 ac830054 3c023a06 34420e00 24033048 ac820058
ac83005c 3c027929 34422600 24032629 ac820060 ac830064 3c020505 34420700
2403407f ac820068 ac83006c 3c020525 34423f00 2403407f ac820070 ac830074
3c02e73c 34425a00 24035a3c ac820078 ac83007c 3c021c1c 34420800 24037f3e
ac820080 ac830084 3c021c3e 34427f00 2403081c ac820088 ac83008c 3c027f22
34421400 24031422 ac820090 ac830094 3c02005f 34425f00 24035f5f ac820098
ac83009c 3c027f01 34427f00 24030609 ac8200a0 ac8300a4 3c028995 34426a00
24030066 ac8200a8 ac8300ac 3c026060 34426000 24036060 ac8200b0 ac8300b4
3c02ffa2 34429400 340394a2 ac8200b8 ac8300bc 3c027e04 34420800 24030804
ac8200c0 ac8300c4 3c027e20 34421000 24031020 ac8200c8 ac8300cc 3c022a1c
34420800 24030808 ac8200d0 ac8300d4 3c022a08 34420800 2403081c ac8200d8
ac8300dc 3c021010 34421000 24031e10 ac8200e0 ac8300e4 3c020c1e 34420c00
24030c1e ac8200e8 ac8300ec 3c023e38 34423000 24033038 ac8200f0 ac8300f4
3c023e0e 34420600 2403060e ac8200f8 ac8300fc 00001021 00001821 ac820100
ac830104 3c025f00 00001821 ac820108 ac83010c 3c020007 24030007 ac820110
ac830114 3c02147f 34421400 2403147f ac820118 ac83011c 3c027f2a 34421200
2403242a ac820120 ac830124 3c020864 34426200 24032313 ac820128 ac83012c
3c025620 34425000 24033649 ac820130 ac830134 3c020703 24030008 ac820138
ac83013c 3c022241 2403001c ac820140 ac830144 3c02221c 24030041 ac820148
ac83014c 3c027f1c 34422a00 24032a1c ac820150 ac830154 3c023e08 34420800
24030808 ac820158 ac83015c 3c027030 24030080 ac820160 ac830164 3c020808
34420800 24030808 ac820168 ac83016c 3c026060 00001821 ac820170 ac830174
3c020804 34420200 24032010 ac820178 ac83017c 3c024945 34423e00 24033e51
ac820180 ac830184 3c027f40 24030042 ac820188 ac83018c 3c024949 34424600
24037249 ac820190 ac830194 3c02494d 34423300 24032141 ac820198 ac83019c
3c02127f 34421000 24031814 ac8201a0 ac8301a4 3c024545 34423900 24032745
ac8201a8 ac8301ac 3c024949 34423100 24033c4a ac8201b0 ac8301b4 3c021109
34420700 24034121 ac8201b8 ac8301bc 3c024949 34423600 24033649 ac8201c0
ac8301c4 3c024929 34421e00 24034649 ac8201c8 ac8301cc 3c021400 00001821
ac8201d0 ac8301d4 3c023400 24030040 ac8201d8 ac8301dc 3c021422 34424100
24030008 ac8201e0 ac8301e4 3c081414 35081400 24091414 ac8801e8 ac8901ec
3c022214 34420800 24030041 ac8201f0 ac8301f4 3c025909 34420600 24030201
ac8201f8 ac8301fc 3c025d59 34424e00 24033e41 ac820200 ac830204 3c021112
34427c00 24037c12 ac820208 ac83020c 3c024949 34423600 24037f49 ac820210
ac830214 3c024141 34422200 24033e41 ac820218 ac83021c 3c024141 34423e00
24037f41 ac820220 ac830224 3c024949 34424100 24037f49 ac820228 ac83022c
3c020909 34420100 24037f09 ac820230 ac830234 3c024151 34427300 24033e41
ac820238 ac83023c 3c020808 34427f00 24037f08 ac820240 ac830244 3c027f41
24030041 ac820248 ac83024c 3c02413f 34420100 24032040 ac820250 ac830254
3c021422 34424100 24037f08 ac820258 ac83025c 3c024040 34424000 24037f40
ac820260 ac830264 3c021c02 34427f00 24037f02 ac820268 ac83026c 3c020810
34427f00 24037f04 ac820270 ac830274 3c024141 34423e00 24033e41 ac820278
ac83027c 3c020909 34420600 24037f09 ac820280 ac830284 3c025121 34425e00
24033e41 ac820288 ac83028c 3c021929 34424600 24037f09 ac820290 ac830294
3c024949 34423200 24032649 ac820298 ac83029c 3c027f01 34420300 24030301
ac8202a0 ac8302a4 3c024040 34423f00 24033f40 ac8202a8 ac8302ac 3c024020
34421f00 24031f20 ac8202b0 ac8302b4 3c023840 34423f00 24033f40 ac8202b8
ac8302bc 3c020814 34426300 24036314 ac8202c0 ac8302c4 3c027804 34420300
24030304 ac8202c8 ac8302cc 3c02494d 34424300 24036159 ac8202d0 ac8302d4
3c024141 34424100 2403007f ac8202d8 ac8302dc 3c020810 34422000 24030204
ac8202e0 ac8302e4 3c024141 34427f00 24030041 ac8202e8 ac8302ec 3c020102
34420400 24030402 ac8202f0 ac8302f4 3c024040 34424000 24034040 ac8202f8
ac8302fc 3c020708 24030003 ac820300 ac830304 3c025478 34424000 24032054
ac820308 ac83030c 3c024444 34423800 24037f28 ac820310 ac830314 3c024444
34422800 24033844 ac820318 ac83031c 3c024428 34427f00 24033844 ac820320
ac830324 3c025454 34421800 24033854 ac820328 ac83032c 3c027e09 34420200
24030008 ac820330 ac830334 3c02a49c 34427800 240318a4 ac820338 ac83033c
3c020404 34427800 24037f08 ac820340 ac830344 3c027d40 24030044 ac820348
ac83034c 3c02403d 24032040 ac820350 ac830354 3c022844 24037f10 ac820358
ac83035c 3c027f40 24030041 ac820360 ac830364 3c027804 34427800 24037c04
ac820368 ac83036c 3c020404 34427800 24037c08 ac820370 ac830374 3c024444
34423800 24033844 ac820378 ac83037c 3c022424 34421800 3403fc18 ac820380
ac830384 3c022418 3442fc00 24031824 ac820388 ac83038c 3c020404 34420800
24037c08 ac820390 ac830394 3c025454 34422400 24034854 ac820398 ac83039c
3c023f44 34422400 24030404 ac8203a0 ac8303a4 3c024020 34427c00 24033c40
ac8203a8 ac8303ac 3c024020 34421c00 24031c20 ac8203b0 ac8303b4 3c023040
34423c00 24033c40 ac8203b8 ac8303bc 3c021028 34424400 24034428 ac8203c0
ac8303c4 3c029090 34427c00 24034c90 ac8203c8 ac8303cc 3c02544c 34424400
24034464 ac8203d0 ac8303d4 3c023641 24030008 ac8203d8 ac8303dc 3c027700
00001821 ac8203e0 ac8303e4 3c023608 24030041 ac8203e8 ac8303ec 3c020204
34420200 24030201 ac8203f0 ac8303f4 3c022326 34423c00 24033c26 ac8203f8
ac8303fc 3c02a161 34421200 24031ea1 ac820400 ac830404 3c024020 34427a00
24033a40 ac820408 ac83040c 3c025455 34425900 24033854 ac820410 ac830414
3c025579 34424100 24032155 ac820418 ac83041c 3c025478 34424200 24032254
ac820420 ac830424 3c025478 34424000 24032155 ac820428 ac83042c 3c025579
34424000 24032054 ac820430 ac830434 3c025272 34421200 24030c1e ac820438
ac83043c 3c025555 34425900 24033955 ac820440 ac830444 3c025454 34425900
24033954 ac820448 ac83044c 3c025454 34425800 24033955 ac820450 ac830454
3c02457c 34424100 00001821 ac820458 ac83045c 3c02457d 34424200 24030002
ac820460 ac830464 3c02457c 34424000 24030001 ac820468 ac83046c 3c021112
34427d00 24037d12 ac820470 ac830474 3c022528 3442f000 3403f028 ac820478
ac83047c 3c025545 24037c54 ac820480 ac830484 3c02547c 34425400 24032054
ac820488 ac83048c 3c02097f 34424900 24037c0a ac820490 ac830494 3c024949
34423200 24033249 ac820498 ac83049c 3c024444 34423a00 24033a44 ac8204a0
ac8304a4 3c024848 34423000 2403324a ac8204a8 ac8304ac 3c024121 34427a00
24033a41 ac8204b0 ac8304b4 3c024020 34427800 24033a42 ac8204b8 ac8304bc
3c02a0a0 34427d00 2403009d ac8204c0 ac8304c4 3c024242 34423d00 24033d42
ac8204c8 ac8304cc 3c024040 34423d00 24033d40 ac8204d0 ac8304d4 3c02ff24
34422400 24033c24 ac8204d8 ac8304dc 3c024943 34426600 2403487e ac8204e0
ac8304e4 3c02fc2f 34422b00 24032b2f ac8204e8 ac8304ec 3c0229f6 34422000
3403ff09 ac8204f0 ac8304f4 3c027e09 34420300 3403c088 ac8204f8 ac8304fc
3c025479 34424100 24032054 ac820500 ac830504 3c02447d 34424100 00001821
ac820508 ac83050c 3c02484a 34423200 24033048 ac820510 ac830514 3c024022
34427a00 24033840 ac820518 ac83051c 3c020a0a 34427200 2403007a ac820520
ac830524 3c021931 34427d00 24037d0d ac820528 ac83052c 3c02292f 34422800
24032629 ac820530 ac830534 3c022929 34422600 24032629 ac820538 ac83053c
3c024d40 34422000 24033048 ac820540 ac830544 3c020808 34420800 24033808
ac820548 ac83054c 3c020808 34423800 24030808 ac820550 ac830554 3c02c8ac
3442ba00 24032f10 ac820558 ac83055c 3c022834 3442fa00 24032f10 ac820560
ac830564 3c027b00 00001821 ac820568 ac83056c 3c022a14 34422200 24030814
ac820570 ac830574 3c022a14 34420800 24032214 ac820578 ac83057c 3c025500
3442aa00 3403aa00 ac820580 ac830584 3c02aa55 3442aa00 3403aa55 ac820588
ac83058c 3c0200ff 00001821 ac820590 ac830594 3c0210ff 24031010 ac820598
ac83059c 3c0214ff 24031414 ac8205a0 ac8305a4 3c02ff00 3442ff00 24031010
ac8205a8 ac8305ac 3c02f010 3442f000 24031010 ac8205b0 ac8305b4 3c0614fc
24071414 ac8605b8 ac8705bc 3c06f700 34c6ff00 24071414 ac8605c0 ac8705c4
3c0aff00 354aff00 00005821 ac8a05c8 ac8b05cc 3c06f404 34c6fc00 24071414
ac8605d0 ac8705d4 3c061710 34c61f00 24071414 ac8605d8 ac8705dc 3c061f10
34c61f00 24071010 ac8605e0 ac8705e4 3c0c141f 240d1414 ac8c05e8 ac8d05ec
3c0c10f0 240d1010 ac8c05f0 ac8d05f4 3c0c001f 358c1000 00006821 ac8c05f8
ac8d05fc 3c0c101f 358c1000 240d1010 ac8c0600 ac8d0604 3c0c10f0 358c1000
240d1010 ac8c0608 ac8d060c 3c0c00ff 358c1000 00006821 ac8c0610 ac8d0614
3c0c1010 358c1000 240d1010 ac8c0618 ac8d061c 3c0c10ff 358c1000 240d1010
ac8c0620 ac8d0624 3c0c00ff 358c1400 00006821 ac8c0628 ac8d062c ac8a0630
ac8b0634 3c0a1f10 354a1700 00005821 ac8a0638 ac8b063c 3c0afc04 354af400
00005821 ac8a0640 ac8b0644 3c0a1710 354a1700 240b1414 ac8a0648 ac8b064c
3c0af404 354af400 240b1414 ac8a0650 ac8b0654 3c0aff00 354af700 00005821
ac8a0658 ac8b065c ac880660 ac890664 3c08f700 3508f700 24091414 ac880668
ac89066c 3c081417 35081400 24091414 ac880670 ac890674 ac860678 ac87067c
3c0614f4 34c61400 24071414 ac860680 ac870684 ac820688 ac83068c 3c021f10
34421f00 00001821 ac820690 ac830694 3c02001f 34421400 00001821 ac820698
ac83069c 3c0200fc 34421400 00001821 ac8206a0 ac8306a4 3c02f010 3442f000
00001821 ac8206a8 ac8306ac 3c02ff10 3442ff00 24031010 ac8206b0 ac8306b4
3c0214ff 34421400 24031414 ac8206b8 ac8306bc 3c02101f 24031010 ac8206c0
ac8306c4 3c0200f0 34421000 00001821 ac8206c8 ac8306cc 2402ff00 3403ffff
ac8206d0 ac8306d4 3c02f0f0 3442f000 3403f0f0 ac8206d8 ac8306dc 3c02ff00
3403ffff ac8206e0 ac8306e4 3c0200ff 3442ff00 00001821 ac8206e8 ac8306ec
3c020f0f 34420f00 24030f0f ac8206f0 ac8306f4 3c024438 34424400 24033844
ac8206f8 ac8306fc 3c024a4a 34423400 3403fc4a ac820700 ac830704 3c020206
34420600 24037e02 ac820708 ac83070c 3c02027e 34420200 2403027e ac820710
ac830714 3c024941 34426300 24036355 ac820718 ac83071c 3c02443c 34420400
24033844 ac820720 ac830724 3c02201e 34422000 2403407e ac820728 ac83072c
3c027e02 34420200 24030602 ac820730 ac830734 3c02e7a5 34429900 340399a5
ac820738 ac83073c 3c02492a 34421c00 24031c2a ac820740 ac830744 3c020172
34424c00 24034c72 ac820748 ac83074c 3c024d4d 34423000 2403304a ac820750
ac830754 3c027848 34423000 24033048 ac820758 ac83075c 3c025a46 34423d00
3403bc62 ac820760 ac830764 3c024949 24033e49 ac820768 ac83076c 3c020101
34427e00 24037e01 ac820770 ac830774 3c022a2a 34422a00 24032a2a ac820778
ac83077c 3c025f44 34424400 24034444 ac820780 ac830784 3c024a44 34424000
24034051 ac820788 ac83078c 3c024a51 34424000 24034044 ac820790 ac830794
3c02ff01 34420300 00001821 ac820798 ac83079c 3c02ff00 3403e080 ac8207a0
ac8307a4 3c026b6b 34420800 24030808 ac8207a8 ac8307ac 3c023624 34423600
24033612 ac8207b0 ac8307b4 3c02090f 34420600 2403060f ac8207b8 ac8307bc
3c021818 00001821 ac8207c0 ac8307c4 3c021010 00001821 ac8207c8 ac8307cc
3c02ff01 34420100 24033040 ac8207d0 ac8307d4 3c020101 34421e00 2403001f
ac8207d8 ac8307dc 3c021d17 34421200 24030019 ac8207e0 ac8307e4 3c023c3c
34423c00 2403003c ac8207e8 ac8307ec 00001021 00001821 ac8207f0 ac8307f4
03e00008 00000000
End CFunction

'
CFunction drawPixel
00000000
8fae0010 8fad0014 8ce70000 240f0001 10ef000f 8fac0020 50e00009 8cab0000
240f0002 50ef0015 8caa0000 240e0003 54ee0020 8fa50018 10000017 8caa0000
00001821 8cca0000 10000019 00001021 8cab0000 000b5827 8dc20000 01625821
00001821 8cca0000 000a5027 8da20000 01425021 1000000e 00001021 00001021
8ccb0000 000b5827 8dc30000 01635821 10000007 00001821 000a5027 8da20000
01425021 00001021 8ccb0000 00001821 8fa50018 8ca60000 14600004 24050001
0166302b 14c00003 30a500ff 00002821 30a500ff 50a0003a 01001021 8fa3001c
8c650000 14400004 24030001 0145282b 14a00003 306300ff 00001821 306300ff
5060002f 01001021 8c830000 10600016 2408ffff 00004021 14400008 00004821
14400004 24020001 2d420020 10400004 24020001 10000003 01424004 24020001
01424804 000b58c0 018b6021 8d820000 00481025 ad820000 8d820004 00491025
10000016 ad820004 14400009 2409ffff 14400004 24020001 2d420020 10400005
24020001 01425004 10000004 000a4027 24020001 01425004 000a4827 000b58c0
018b6021 8d820000 00481024 ad820000 8d820004 00491024 ad820004 01001021
03e00008 01201821
End CFunction
'
CFunction getnextupdate
00000000
27bdffd8 afb50024 afb40020 afb3001c afb20018 afb10014 afb00010 8fb90038
8faf003c 8fb80040 8ccd0000 8f220000 01a2102b 24080002 10400053 00004821
01a08821 03ad8021 27a20008 004d7021 8cac0000 8cf30000 0193102b 10400040
000c90c0 01f21021 8c430004 8c420000 afa20000 afa30004 03129021 8e420000
8e430004 afa20008 afa3000c 0200a021 920b0000 91c20000 104b0028 01c0a821
10000010 03b18821 8d420008 8d43000c afa20000 afa30004 01209021 8d220000
8d230004 afa20008 afa3000c 928b0000 25290008 92a20000 104b001e 254a0008
03b18821 a22b0008 8fa20008 8fa3000c ae420000 ae430004 ac8b0000 8cc20000
544d000a acac0000 8ca30000 24630001 546c0006 acac0000 aca30000 acc20000
00004021 10000018 00004821 accd0000 24080001 10000014 00004821 01804021
25890001 000948c0 03094821 000c50c0 01ea5021 25080001 1513ffd3 01006021
aca00000 26310001 02206821 26100001 8f220000 0222102b 1440ffb5 25ce0001
24080002 00004821 01001021 01201821 8fb50024 8fb40020 8fb3001c 8fb20018
8fb10014 8fb00010 03e00008 27bd0028
End CFunction
'
CFunction fastfillrect
00000000
27bdfff8 8ca80000 8ce70000 8fa9001c 8d290000 00e85021 012a502b 01284823
012a380b 00e84021 8ccf0000 8fa60018 8cd80000 8fa60020 8cc60000 030f3821
00c7382b 00cf3023 00c7c00b 030fc021 01f8302b 10c00026 8fa30024 24190001
000f58c2 8caa0000 0148302b 10c0001d 31e20007 00596804 7c0d7420 000d6827
7c0d6c20 000a48c0 00694821 03ab5821 8d260000 8d270004 afa60000 afa70004
8c860000 10c00005 01206021 91660000 01c63025 10000004 a1660000 91660000
01a63024 a1660000 8fa60000 8fa70004 ad860000 ad870004 254a0001 1548ffec
25290008 25ef0001 55f8ffde 000f58c2 00001821 03e00008 27bd0008
End CFunction

2014-11-16_164324_cfunctionSPI.zip
Edited by matherp 2014-11-17
 
G8JCF

Guru

Joined: 15/05/2014
Location: United Kingdom
Posts: 676
Posted: 07:43am 16 Nov 2014
Copy link to clipboard 
Print this post

Peter

Absolutely Brilliant. Really great to see CFunctions being taken up with such gusto.

Hopefully as more people get to grips with CFunctions, the power of a friendly forgiving and immediate environment of Basic coupled with the raw power of compiled 'C' will push MMBasic and uMite into more and more areas.

You can speed up the code/compile/append/download cycle further !

a) In CFuncGen set AutoGenerate ON - then whenever CFuncGen detects a change in the .ELF file, it will automatically do a Refresh and generate the CFunction(s)

b) Every time CFuncGen generates the CFunction .bas file, CFuncGen also copies the text of the CFunction(s) to the Windows Clipboard, so all you have to is Ctrl+V to paste the CFunction into your code MMEdit

c) If you use MCPP and the 'run external' feature in MMEdit, then you just need a #include <path to CFunction .bas file> at the end of your MMBasic program and whenever MMEdit downloads your MMBasic code to the uMite it will automatically'include' in the latest CFunction code - see Tutorial 4 Advanced Topics.

If you do a), and c), then all you need to do is hit the "Blue Hammer" in MPLabX, and then the 'Blue Running Man with torch' in MMedit to have your new code running on your uMite. (in MMEdit set menu Advanced | Auto run on load).

Excellent - I'm going to get some of these displays !

PeterEdited by G8JCF 2014-11-17
The only Konstant is Change
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5905
Posted: 10:31am 16 Nov 2014
Copy link to clipboard 
Print this post

When I see projects like this I am glad that MMEdit has been of some use.

Like Peter, I am going to get some of these displays.

Jim

VK7JH
MMedit   MMBasic Help
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 8584
Posted: 10:51am 16 Nov 2014
Copy link to clipboard 
Print this post

Jim

One possible "advanced" option that could be added to MMedit would be to tokenise the variable and constant names and shorten them. I love long names but because of the way micromite stores the program they do take up extra space. Next time you have nothing to do perhaps you could have a think about a "crunch-plus" option?

Best Regards

Peter
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3165
Posted: 11:32am 16 Nov 2014
Copy link to clipboard 
Print this post

This is just fantastic. An impressive programming effort and a very useful library.

Thanks for the inspiration, in the next beta I hope to detect when a MIPS exception has occured in a CFunction and print out the cause and address of the offending instruction (the processor will still reset though).

Geoff
Geoff Graham - http://geoffg.net
 
twofingers
Guru

Joined: 02/06/2014
Location: Germany
Posts: 1133
Posted: 11:37am 16 Nov 2014
Copy link to clipboard 
Print this post

@Peter M.,

Thx a lot. I think this will be quite useful for many people here. It's very important, to have some "how-to-do"s to bring MMbasic further. The more work examples the more users looking to MMBasic.
Good job! :)

@Jim,
just yesterday I tried to crunch a program to have faster load time (on Maximite).

@Perter C.,
again: good job, your Cfunction tools. Without them ... it would much more difficult.
I Guess this will also motivate Geoff to continue.

Regards
Michael
(still without umite or oleds, but soon ...)
 
G8JCF

Guru

Joined: 15/05/2014
Location: United Kingdom
Posts: 676
Posted: 12:04pm 16 Nov 2014
Copy link to clipboard 
Print this post

Hi Peter (@matherp)

[Quote=matherp]One possible "advanced" option that could be added to MMedit would be to tokenise the variable and constant names and shorten them. I love long names but because of the way micromite stores the program they do take up extra space. Next time you have nothing to do perhaps you could have a think about a "crunch-plus" option?

Using the MCPP preprocessor, I use #define's to shorten my symbols from long friendly/meaningful ones to 1 or 2 characters long when the MMBasic code is downloaded to the uMite.
eg

#define mmprog32rpc mp
#define XferFastData S1
#define XferData32 S2
#define XferData F3
#define SendCommand S4
#define XferInstruction S5
#define Initialise S6
#define SetMode S7
#define ExitProgMode S8
#define Clock S9
#define Send8Bits SA


#define also enables one to define constants, which unlike MMBasic variables/constants take up no memory space and seem to execute more quickly,

eg

'Define I/O pins
#define PGD 5
#define CLK 6
#define MCLR 7

#define LOW 0
#define HIGH 1

#define PULSEWIDTH .01


then use #ifdef/#endif with #define to include/omit code blocks as required - so much cleaner and less error prone than commenting in/out blocks of code.

eg

#ifdef DEBUG
DEBUGOPEN
DEBUGOUT ""
DEBUGOUT "Debug Channel Opened @" ; TIME$
#endif


Whilst it may seem somewhat "UN-Basic like" to be using a preprocessor, the ability to decrease memory footprint, improve performance, properly document and structure one's code is really important as code size increases, and maintainability becomes more important.

MMEdit's "Auto Run External on Load" is a really, really important capability.

Anyway, once again, may I congratulate you for taking the initiative so boldly !

Peter - GM8JCF
The only Konstant is Change
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5905
Posted: 12:07pm 16 Nov 2014
Copy link to clipboard 
Print this post

  matherp said   Jim

One possible "advanced" option that could be added to MMedit would be to tokenise the variable and constant names and shorten them. I love long names but because of the way micromite stores the program they do take up extra space. Next time you have nothing to do perhaps you could have a think about a "crunch-plus" option?

Best Regards

Peter


It is something that has been requested before and I have it on the 'have a look at' list.

I have just found another more important bug to fix. Nothing critical, just formatting IF when it has 'IF(' without a space.

Jim
VK7JH
MMedit   MMBasic Help
 
G8JCF

Guru

Joined: 15/05/2014
Location: United Kingdom
Posts: 676
Posted: 12:34pm 16 Nov 2014
Copy link to clipboard 
Print this post

Jim

I think it may be better to develop a separate "Cruncher" program and have that "Auto run external on load" from MMEdit rather than expand MMedit itself.

As you pointed out to me way back when, Hugh has done extensive work on Crunching (albeit written in MMBasic), but "it shouldn't be difficult" (famous last words) to convert/port Hugh's code into a VB/LibertyB/C# program running on the PC.

Peter

PS, the MCPP preprocessor referred to above is available from http://www.g8jcf.dyndns.org/mmbasic

Edited by G8JCF 2014-11-17
The only Konstant is Change
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 8584
Posted: 02:26am 17 Nov 2014
Copy link to clipboard 
Print this post

BUG

In two subroutines drawCircleHelper and drawLine I have put the LOCAL definition of the return from the drawpixel cFunction inside a conditional statement so depending how they get called there will be a "not-defined" bug at run time. These definitions should be moved to a simple declaration "LOCAL dp" at the top of the two subroutines.

This happened when I was changing drawpixel from a basic subroutine without a return to a cFunction - sorry

Best Regards

Peter
 
paceman
Guru

Joined: 07/10/2011
Location: Australia
Posts: 1328
Posted: 02:33am 17 Nov 2014
Copy link to clipboard 
Print this post

@Peter M,

Great effort Peter and my thanks too. I've just ordered a couple of the OLED displays to try the library with - hould be fun.

Greg
 
micronut
Newbie

Joined: 03/09/2014
Location: United States
Posts: 37
Posted: 04:52pm 17 Nov 2014
Copy link to clipboard 
Print this post

matherp,
Awesome job! I've been trying to get a ST7781R TFT to work with the Micromite using CFunctions but after 2 weeks of head pounding I cannot get it to work. I have a Zolentech 128x64 Graphic display that is similar to your Nokia. I think I'll get that going then slowly work my way up to it. I have a couple of LCDs so I want to see if I can eventually get your library working on all of them. Thanks for posting your code.
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 8584
Posted: 06:40am 18 Nov 2014
Copy link to clipboard 
Print this post

New version with significant performance improvements particularly for SSD1306. The fastfillrect cFunction has been generalised to work for any screen rotation (now also used for vertical and horizontal line drawing) and display specific refresh algorithms have been created that use the ability of i2c to send large amounts of data as a single transaction. The "main" program now tests/uses all drawing primitives. A single constant "displayinuse" determines which display to use.
I've now got to stop fiddling with this and get on with something more constructive
2014-11-18_195823_cfunctionSPI.zip Edited by matherp 2014-11-19
 
paceman
Guru

Joined: 07/10/2011
Location: Australia
Posts: 1328
Posted: 01:31pm 18 Nov 2014
Copy link to clipboard 
Print this post


But not as much fun?
 
twofingers
Guru

Joined: 02/06/2014
Location: Germany
Posts: 1133
Posted: 04:57am 19 Nov 2014
Copy link to clipboard 
Print this post

Hallo Peter,

I didn't try, but the code looks good! Well done!
(I think there should be more feedback here!)

Regards

Michael
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 8584
Posted: 07:42am 24 Nov 2014
Copy link to clipboard 
Print this post

Another new version. The variables and functions are now fully typed so it will run whatever OPTION DEFAULT is specified.
The font array is replaced by a data Cfunction - many thanks to Peter Carnegie (G8JCF) for sorting out how to do this. This has saved significant space.
Also variable, subroutine and function names have been shortened to save space.


' Monochrome Port of Adafruit graphics library with drivers for i2c SSD1306 display
'
' drawing primitives assume a graphics display where top left is point 0,0
'
'sub setrot(x) 'sets screen rot: 0=normal,1=invert,2=rotate right,3-rotate left
'sub dcirc(x0,y0,r) 'x,y coordinates of centre,radius
'sub fcirc(x0,y0,r) 'x,y coordinates of centre,radius
'sub dtri(x0,y0,x1,y1,x2,y2) 'three coordinate pairs
'sub ftri (x0,y0,x1,y1,x2,y2) 'three coordinate pairs
'sub dChar(xx,yy,ch,sz,orientation) 'x,y coordinates of top left of first character,ascii character,size,orientation
'sub pstring(xx0,yy0,text$,sz,orientation) 'x,y coordinates of top left of first character,text string,size,orientation
'sub dLine(xx0,yy0,xx1,yy1)' x,y of start line,x,y of end line
'sub dRect(x,y,w,h) 'x,y coordinate of top left,width,height
'sub frect(x,y,w,h)'x,y coordinate of top left,width,height
'sub drndRect(x,y,w,h,r) 'x,y coordinates of top left,width,height,radius of corner
'sub frndRect(x,y,w,h,r) 'x,y coordinates of top left,width,height,radius of corner
'
' These routines just update the memory image of the display
' Use the refresh command to write to the display as required
'
'CFunctions
'unsigned long long ffr(unsigned int *sense,unsigned int *x,unsigned int *y,unsigned int *width,unsigned int *height,unsigned int *rotation,unsigned int *screenwidth,unsigned int *screenheight,unsigned long long sc[]){
'unsigned long long S_getnextupdate(unsigned char outchar[],unsigned int *startcol,unsigned int *startrow,unsigned int *col,unsigned int *row,unsigned int *maxcols,unsigned int *maxrows,unsigned long long sc[],unsigned long long dd[]){
'unsigned long long pix(unsigned int *onoff,unsigned int *x,unsigned int *y,unsigned int *rot,unsigned int *wi,unsigned int *ht,unsigned long long p_array[])
'data cFunction FONT contains the pixel maps for the character set
'
cpu 48
OPTION EXPLICIT
OPTION DEFAULT FLOAT
'option autorun on
const normal=0
const inverse=1
const rt_right=2
const rt_left=3
const ON=&B1
const OFF=&B0
const ch=8
const cw=6
'
' SSD1306 Display specific constants
const S_wi=128
const S_ht=64
const S_nr=S_ht\8 'memory is arranged as rows 8 bits high
const S_i2caddr=&H3C
const S_SETCONTRAST=&H81
const S_DISPLAYALLON_RESUME=&HA4
const S_NORMALDISPLAY=&HA6
const S_DISPLAYOFF=&HAE
const S_DISPLAYON=&HAF
const S_SETDISPLAYOFFSET=&HD3
const S_SETCOMPINS=&HDA
const S_SETVCOMDETECT=&HDB
const S_SETDISPLAYCLOCKDIV=&HD5
const S_SETPRECHARGE=&HD9
const S_SETMULTIPLEX=&HA8
const S_SETSTARTLINE=&H40
const S_MEMORYMODE=&H20
const S_COMSCANDEC=&HC8
const S_SEGREMAP=&HA0
const S_CHARGEPUMP=&H8D
'
dim as integer wi,ht,nr,i2caddr,rot_ht,rot_wi,sz,nc,rot,i,j,k,char,AddrOfFo nt
dim as integer sc(128),dd(128) 'set up arrays for screen map to mimic display
init:
print "Starting initialisation"
print "Using SSD1306"
wi=S_wi
ht=S_ht
nr=S_nr
i2caddr=S_i2caddr
initSdisplay 'initialise the display
AddrOfFont=PEEK(CFunAddr FONT) '
setrot(normal)
print "starting main"
'
Main:
' test drawing rectangles
S_clearsc
for i=0 to 3
setrot(i)
frect(5,5,10,15)
drect(2,2,16,21)
S_refresh
next i
pause 2000
' test drawing rounded rectangles
S_clearsc
for i=0 to 3
setrot(i)
frndrect(5,5,10,15,4)
drndrect(2,2,16,21,6)
S_refresh
next i
pause 2000
' test drawing circles
S_clearsc
for i=0 to 3
setrot(i)
fcirc(10,10,7)
dcirc(10,10,9)
S_refresh
next i
pause 2000
' test drawing triangles and line drawing
S_clearsc
for i=0 to 3
setrot(i)
ftri(4,4,20,6,12,14)
dtri(1,2,24,4,12,17)
S_refresh
next i
pause 2000
' test character output and string output at all orientations
for sz=1 to 3
nc=2 'number of characters in the string I'm using
S_clearsc
for i=0 to 3
setrot(i)
pstring(0,0,"0"+chr$(48+i),sz,normal)
next i
S_refresh
pause 3000
S_clearsc
for i=0 to 3
setrot(i)
pstring(cw*sz*nc-1,ch*sz-1,"1"+chr$(48+i),sz,inverse)
next i
S_refresh
pause 3000
S_clearsc
for i=0 to 3
setrot(i)
pstring(ch*sz-1,0,"2"+chr$(48+i),sz,rt_right)
next i
S_refresh
pause 3000
S_clearsc
for i=0 to 3
setrot(i)
pstring(0,cw*sz*nc-1,"3"+chr$(48+i),sz,rt_left)
next i
S_refresh
pause 3000
next sz
goto main
end
'
' SSD1306 Display specific routines
'
sub initSdisplay 'i2c oled
I2C OPEN 400,1000
S_command(S_DISPLAYOFF)' &HAE
S_command(S_SETDISPLAYCLOCKDIV)'&HD5
S_command(&H80)'the suggested ratio &H80
S_command(S_SETMULTIPLEX)'&HA8
S_command(&H3F)'
S_command(S_SETDISPLAYOFFSET)'&HD3
S_command(&H0)'no offset
S_command(S_SETSTARTLINE )'line #0
S_command(S_CHARGEPUMP)'&H8D
S_command(&H14)
S_command(S_MEMORYMODE)' &H20
S_command(&H00)'&H0 act like ks0108
S_command(S_SEGREMAP OR 1);
S_command(S_COMSCANDEC);
S_command(S_SETCOMPINS)' &HDA
S_command(&H12)
S_command(S_SETCONTRAST)'&H81
S_command(&HCF)
S_command(S_SETPRECHARGE)'&Hd9
S_command(&HF1)
S_command(S_SETVCOMDETECT)'&HDB
S_command(&H40)
S_command(S_DISPLAYALLON_RESUME)'&HA4
S_command(S_NORMALDISPLAY)'&HA6
S_command(S_DISPLAYON)
S_clearsc
end sub
'
Sub S_Command(command as integer)
I2C WRITE i2caddr,0,2,&H00,command
end sub
'
'
sub S_SendData(Dchar as integer)
I2C WRITE i2caddr,0,2,&H40,Dchar
end sub
'
sub S_refresh
local as integer rows=0,cols=0,startrow,startcol,retstatus
local outchar$=""
S_cursor(0,0)
do
retstatus=Sgetnextupdate(outchar$,startcol,startrow,cols,row s,wi,nr,sc(),dd())
if retstatus<>0 then
S_cursor(startcol,startrow)
i2c write i2caddr,0,len(outchar$),outchar$
endif
loop while retstatus<>0
end sub
'
Sub S_Clearsc
local as integer i,j
for i=0 to 7
S_cursor(0,i)
for j=0 to 127 step 16
I2C WRITE i2caddr,0,33,&H40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0
next j
next i
for i=0 to 127
sc(i)=0
dd(i)=0
next i
end sub
'
sub S_Cursor(x as integer,y as integer)
S_command(&HB0+y) 'set page address
S_command(&H10+(x>>4 and &H0F)) 'set high col address
S_command(&H00+(x AND &H0f)) 'set low col address
end sub
'
' Generic drawing routines
'
sub dcirc(x0 as integer,y0 as integer,r as integer) 'x,y coordinates of centre,radius
local as integer f=1-r,ddF_x=1,ddF_y=-2 * r,x=0,y=r,dp
dp=pix(ON,x0,y0+r,rot,wi,ht,sc())
dp=pix(ON,x0,y0-r,rot,wi,ht,sc())
dp=pix(ON,x0+r,y0,rot,wi,ht,sc())
dp=pix(ON,x0-r,y0,rot,wi,ht,sc())
do while (x<y)
if f>=0 then
y=y-1
ddF_y=ddF_y+2
f=f+ddF_y
endif
x=x+1
ddF_x=ddF_x+2
f=f+ddF_x
dp=pix(ON,x0+x,y0+y,rot,wi,ht,sc())
dp=pix(ON,x0-x,y0+y,rot,wi,ht,sc())
dp=pix(ON,x0+x,y0-y,rot,wi,ht,sc())
dp=pix(ON,x0-x,y0-y,rot,wi,ht,sc())
dp=pix(ON,x0+y,y0+x,rot,wi,ht,sc())
dp=pix(ON,x0-y,y0+x,rot,wi,ht,sc())
dp=pix(ON,x0+y,y0-x,rot,wi,ht,sc())
dp=pix(ON,x0-y,y0-x,rot,wi,ht,sc())
loop
end sub
'
sub dtri(x0 as integer,y0 as integer,x1 as integer,y1 as integer, x2 as integer,y2 as integer) 'three coordinate pairs
dLine(x0,y0,x1,y1)
dLine(x1,y1,x2,y2)
dLine(x2,y2,x0,y0)
end sub
'
sub ftri (x0 as integer,y0 as integer,x1 as integer,y1 as integer, x2 as integer,y2 as integer) 'three coordinate pairs
local as integer a,b,y,dp,last
if (y0>y1) then
swap(y0,y1)
swap(x0,x1)
endif
if (y1>y2) then
swap(y2,y1)
swap(x2,x1)
endif
if (y0>y1) then
swap(y0,y1)
swap(x0,x1)
endif
if(y0=y2) then ' Handle awkward all-on-same-line case as its own thing
a=x0
b=x0
if(x1<a) then
a=x1
else
if(x1>b) then b=x1
endif
if(x2<a) then
a=x2
else
if(x2>b) then b=x2
endif
dFastHLine(a,y0,b-a+1)
exit sub
endif
local dx01=x1-x0
local dy01=y1-y0
local dx02=x2-x0
local dy02=y2-y0
local dx12=x2-x1
local dy12=y2-y1
local sa=0
local sb=0
if(y1=y2) then
last=y1 'Include y1 scanline
else
last=y1-1 ' Skip it
endif
for y=y0 to last
a=x0+sa \ dy01
b=x0+sb \ dy02
sa=sa+dx01
sb=sb+dx02
a=x0+(x1-x0) * (y-y0) \ (y1-y0)
b=x0+(x2-x0) * (y-y0) \ (y2-y0)
if(a>b) then swap(a,b)
dp=ffr(ON,a,y,b-a+1,1,rot,wi,ht,sc())
next y
sa=dx12 * (y-y1)
sb=dx02 * (y-y0)
do while y<=y2
a=x1+sa \ dy12
b=x0+sb \ dy02
sa=sa+dx12
sb=sb+dx02
a=x1+(x2-x1) * (y-y1) \ (y2-y1)
b=x0+(x2-x0) * (y-y0) \ (y2-y0)
if(a>b) then swap(a,b)
dp=ffr(ON,a,y,b-a+1,1,rot,wi,ht,sc())
y=y+1
loop
end sub
'
sub pstring(xx0 as integer,yy0 as integer,text$ as string,sz as integer,orientation as integer) 'x,y coordinates of top left of first character,text string,size,orientation
local as integer i,c,x=xx0,y=yy0
for i=1 to len(text$)
c=asc(mid$(text$,i,1))
dchar(x,y,c,sz,orientation)
on orientation+1 goto pnormal,pinvert,prtright,prtleft
pnormal:
x=x+(6*sz)
goto pcontinue
pinvert:
x=x-(6*sz)
goto pcontinue
prtright:
y=y+(6*sz)
goto pcontinue
prtleft:
y=y-(6*sz)
pcontinue:
next i
end sub
'
sub dLine(xx0 as integer,yy0 as integer,xx1 as integer,yy1 as integer) ' x,y of start line,x,y of end line
local as integer dx,dy,x0=xx0,y0=yy0,x1=xx1,y1=yy1,err,ystep,dp,steep=(abs(y1 -y0))>(abs(x1-x0))
if (steep) then
swap(x0,y0)
swap(x1,y1)
endif
if (x0>x1) then
swap(x0,x1)
swap(y0,y1)
endif
dx=x1-x0
dy=abs(y1-y0)
err=dx \ 2
if y0<y1 then
ystep=1
else
ystep=-1
endif
do while x0<=x1
if (steep) then
dp=pix(ON,y0,x0,rot,wi,ht,sc())
else
dp=pix(ON,x0,y0,rot,wi,ht,sc())
endif
err=err-dy
if err<0) then
y0=y0+ystep
err=err+dx
endif
x0=x0+1
loop
end sub
'
sub swap (a as integer,b as integer)
local as integer t
t=b
b=a
a=t
end sub
'
sub dRect(x as integer,y as integer,w as integer,h as integer) 'x,y coordinate of top left,wi,ht
local as integer a,dp
dp=ffr(ON,x,y,w,1,rot,wi,ht,sc())
a=y+h-1
dp=ffr(ON,x,a,w,1,rot,wi,ht,sc())
dp=ffr(ON,x,y,1,h,rot,wi,ht,sc())
a=x+w-1
dp=ffr(ON,a,y,1,h,rot,wi,ht,sc())
end sub
'
sub frect(x as integer,y as integer,w as integer,h as integer) 'x,y coordinate of top left,width,height
local as integer dp
dp=ffr(ON,x,y,w,h,rot,wi,ht,sc())
end sub
'
FUNCTION Getchar(char as integer) as integer
local as integer i=char<<3
Getchar=PEEK(WORD AddrOfFont+i)+(PEEK(WORD AddrOfFont+i+4)<<32)
END FUNCTION
'
sub dChar(xx as integer,yy as integer,ch as integer,sz as integer,orientation as integer) 'x,y coordinates of top left of first character,ascii character,size,orientation
local as integer i,j,x=xx,y=yy,dp,addr,character
character=getchar(ch) 'loads the character
on orientation+1 goto dnormal,dinvert,drtright,drtleft
dnormal:
for i=0 to 5
for j=0 to 7
if (character>>(i*8+j)) and 1 then
if (sz=1) then
dp=pix(ON,x+5-i,y+j,rot,wi,ht,sc())
else
dp=ffr(ON,x+(5-i)*sz,y+(j*sz),sz,sz,rot,wi,ht,sc())
endif
else
if (sz=1) then
dp=pix(OFF,x+5-i,y+j,rot,wi,ht,sc())
else
dp=ffr(OFF,x+(5-i)*sz,y+(j*sz),sz,sz,rot,wi,ht,sc())
endif
endif
next j
next i
exit sub
'
dinvert:
for i=0 to 5 'step down the lines
for j=0 to 7
if (character>>(8*(5-i)+7-j)) and 1 then
if (sz=1) then
dp=pix(ON,x-i,y+j-7,rot,wi,ht,sc())
else
dp=ffr(ON,x-sz+1-(i*sz),y-sz+1+((j-7)*sz),sz,sz,rot,wi,ht,sc ())
endif
else
if (sz=1) then
dp=pix(OFF,x-i,y+j-7,rot,wi,ht,sc())
else
dp=ffr(OFF,x-sz+1-(i*sz),y-sz+1+((j-7)*sz),sz,sz,rot,wi,ht,s c())
endif
endif
next j
next i
exit sub
'
drtright:
for i=0 to 7 'step across the rows
for j=0 to 5
if (character>>((5-j)*8+i)) and 1 then
if (sz=1) then
dp=pix(ON,x-i,y+j,rot,wi,ht,sc())
else
dp=ffr(ON,x-sz+1-i*sz,y+(j)*sz,sz,sz,rot,wi,ht,sc())
endif
else
if (sz=1) then
dp=pix(OFF,x-i,y+j,rot,wi,ht,sc())
else
dp=ffr(OFF,x-sz+1-i*sz,y+(j)*sz,sz,sz,rot,wi,ht,sc())
endif
endif
next j
next i
exit sub
drtleft:
for i=0 to 7 'step across the rows
for j=0 to 5
' if bits(5-j,i) then
if (character>>(8*j+7-i)) and 1 then
if (sz=1) then
dp=pix(ON,x-i+7,y+j-5,rot,wi,ht,sc())
else
dp=ffr(ON,x-i*sz+7*sz+1,y+j*sz-6*sz+1,sz,sz,rot,wi,ht,sc())
endif
else
if (sz=1) then
dp=pix(OFF,x-i+7,y+j-5,rot,wi,ht,sc())
else
dp=ffr(OFF,x-i*sz+7*sz+1,y+j*sz-6*sz+1,sz,sz,rot,wi,ht,sc())
endif
endif
next j
next i
end sub
'

sub fcirc(x0 as integer,y0 as integer,r as integer) 'x,y coordinates of centre,radius
local as integer dp
dp=ffr(ON,x0,y0-r,1,2*r+1,rot,wi,ht,sc())
fcircH(x0,y0,r,3,0);
end sub
'
sub drndRect(x as integer,y as integer,w as integer,h as integer,r as integer) 'x,y coordinates of top left,width,height,radius of corner
local as integer dp
dp=ffr(ON,x+r,y,w-2*r,1,rot,wi,ht,sc())
dp=ffr(ON,x+r,y+h-1,w-2*r,1,rot,wi,ht,sc())
dp=ffr(ON,x,y+r,1,h-2*r,rot,wi,ht,sc())
dp=ffr(ON,x+w-1,y+r,1,h-2*r,rot,wi,ht,sc())
dcircH(x+r,y+r,r,1)
dcircH(x+w-r-1,y+r,r,2)
dcircH(x+w-r-1,y+h-r-1,r,4)
dcircH(x+r,y+h-r-1,r,8)
end sub
'
sub dcircH( x0 as integer,y0 as integer,r as integer,cn as integer)
local as integer f=1-r,ddF_x=1,ddF_y=-2 * r,x=0,y=r,dp
do while (x<y)
if (f>=0) then
y=y-1
ddF_y=ddF_y+2
f=f+ddF_y
endif
x=x+1
ddF_x=ddF_x+2
f=f+ddF_x
if (cn and 4) then
dp=pix(ON,x0+x,y0+y,rot,wi,ht,sc())
dp=pix(ON,x0+y,y0+x,rot,wi,ht,sc())
endif
if (cn and 2) then
dp=pix(ON,x0+x,y0-y,rot,wi,ht,sc())
dp=pix(ON,x0+y,y0-x,rot,wi,ht,sc())
endif
if (cn and 8) then
dp=pix(ON,x0-y,y0+x,rot,wi,ht,sc())
dp=pix(ON,x0-x,y0+y,rot,wi,ht,sc())
endif
if (cn and 1) then
dp=pix(ON,x0-y,y0-x,rot,wi,ht,sc())
dp=pix(ON,x0-x,y0-y,rot,wi,ht,sc())
endif
loop
end sub
'
sub fcircH(x0 as integer,y0 as integer,r as integer,cn as integer,delta as integer)
local as integer dp,f=1-r,ddF_x=1,ddF_y=-2 * r,x=0,y=r
do while x<y
if f>=0 then
y=y-1
ddF_y=ddF_y+2
f=f+ddF_y
endif
x=x+1
ddF_x=ddF_x+2
f=f+ddF_x

if (cn and 1) then
dp=ffr(ON,x0+x,y0-y,1,2*y+1+delta,rot,wi,ht,sc())
dp=ffr(ON,x0+y,y0-x,1,2*x+1+delta,rot,wi,ht,sc())
endif
if (cn and 2) then
dp=ffr(ON,x0-x,y0-y,1,2*y+1+delta,rot,wi,ht,sc())
dp=ffr(ON,x0-y,y0-x,1,2*x+1+delta,rot,wi,ht,sc())
endif
loop
end sub
'
sub frndRect(x as integer,y as integer,w as integer,h as integer,r as integer) 'x,y coordinates of top left,width,height,radius of corner
local as integer dp
dp=ffr(ON,x+r,y,w-2*r,h,rot,wi,ht,sc())
fcircH(x+w-r-1,y+r,r,1,h-2*r-1)
fcircH(x+r,y+r,r,2,h-2*r-1)
end sub
'
sub setrot(x as integer) 'sets screen rotation: 0=normal,1=invert,2=rotate right,3-rotate left
rot=(x and 3)
rot_wi=wi
rot_ht=ht
if x>=2 then
rot_wi=ht
rot_ht=wi
endif
end sub
'
' CFunctions
'
CFunction font
00000000
00000000 00000000 00000000 00000000
4f5b3e00 00003e5b 4f6b3e00 00003e6b 7c3e1c00 00001c3e 7e3c1800 0000183c
7d571c00 00001c57 7f5e1c00 00001c5e 3c180000 00000018 c3e7ff00 0000ffe7
24180000 00000018 dbe7ff00 0000ffe7 3a060e00 00003048 79292600 00002629
05050700 0000407f 05253f00 0000407f e73c5a00 00005a3c 1c1c0800 00007f3e
1c3e7f00 0000081c 7f221400 00001422 005f5f00 00005f5f 7f017f00 00000609
89956a00 00000066 60606000 00006060 ffa29400 000094a2 7e040800 00000804
7e201000 00001020 2a1c0800 00000808 2a080800 0000081c 10101000 00001e10
0c1e0c00 00000c1e 3e383000 00003038 3e0e0600 0000060e 5f000000 00000000
00070000 00000007 147f1400 0000147f 7f2a1200 0000242a 08646200 00002313
56205000 00003649 07030000 00000008 22410000 0000001c 221c0000 00000041
7f1c2a00 00002a1c 3e080800 00000808 70300000 00000080 08080800 00000808
60600000 00000000 08040200 00002010 49453e00 00003e51 7f400000 00000042
49494600 00007249 494d3300 00002141 127f1000 00001814 45453900 00002745
49493100 00003c4a 11090700 00004121 49493600 00003649 49291e00 00004649
14000000 00000000 34000000 00000040 14224100 00000008 14141400 00001414
22140800 00000041 59090600 00000201 5d594e00 00003e41 11127c00 00007c12
49493600 00007f49 41412200 00003e41 41413e00 00007f41 49494100 00007f49
09090100 00007f09 41517300 00003e41 08087f00 00007f08 7f410000 00000041
413f0100 00002040 14224100 00007f08 40404000 00007f40 1c027f00 00007f02
08107f00 00007f04 41413e00 00003e41 09090600 00007f09 51215e00 00003e41
19294600 00007f09 49493200 00002649 7f010300 00000301 40403f00 00003f40
40201f00 00001f20 38403f00 00003f40 08146300 00006314 78040300 00000304
494d4300 00006159 41414100 0000007f 08102000 00000204 41417f00 00000041
01020400 00000402 40404000 00004040 07080000 00000003 54784000 00002054
44443800 00007f28 44442800 00003844 44287f00 00003844 54541800 00003854
7e090200 00000008 a49c7800 000018a4 04047800 00007f08 7d400000 00000044
403d0000 00002040 28440000 00007f10 7f400000 00000041 78047800 00007c04
04047800 00007c08 44443800 00003844 24241800 0000fc18 2418fc00 00001824
04040800 00007c08 54542400 00004854 3f442400 00000404 40207c00 00003c40
40201c00 00001c20 30403c00 00003c40 10284400 00004428 90907c00 00004c90
544c4400 00004464 36410000 00000008 77000000 00000000 36080000 00000041
02040200 00000201 23263c00 00003c26 a1611200 00001ea1 40207a00 00003a40
54555900 00003854 55794100 00002155 54784200 00002254 54784000 00002155
55794000 00002054 52721200 00000c1e 55555900 00003955 54545900 00003954
54545800 00003955 457c4100 00000000 457d4200 00000002 457c4000 00000001
11127d00 00007d12 2528f000 0000f028 55450000 00007c54 547c5400 00002054
097f4900 00007c0a 49493200 00003249 44443a00 00003a44 48483000 0000324a
41217a00 00003a41 40207800 00003a42 a0a07d00 0000009d 42423d00 00003d42
40403d00 00003d40 ff242400 00003c24 49436600 0000487e fc2f2b00 00002b2f
29f62000 0000ff09 7e090300 0000c088 54794100 00002054 447d4100 00000000
484a3200 00003048 40227a00 00003840 0a0a7200 0000007a 19317d00 00007d0d
292f2800 00002629 29292600 00002629 4d402000 00003048 08080800 00003808
08083800 00000808 c8acba00 00002f10 2834fa00 00002f10 7b000000 00000000
2a142200 00000814 2a140800 00002214 5500aa00 0000aa00 aa55aa00 0000aa55
00ff0000 00000000 10ff0000 00001010 14ff0000 00001414 ff00ff00 00001010
f010f000 00001010 14fc0000 00001414 f700ff00 00001414 ff00ff00 00000000
f404fc00 00001414 17101f00 00001414 1f101f00 00001010 141f0000 00001414
10f00000 00001010 001f1000 00000000 101f1000 00001010 10f01000 00001010
00ff1000 00000000 10101000 00001010 10ff1000 00001010 00ff1400 00000000
ff00ff00 00000000 1f101700 00000000 fc04f400 00000000 17101700 00001414
f404f400 00001414 ff00f700 00000000 14141400 00001414 f700f700 00001414
14171400 00001414 1f101f00 00001010 14f41400 00001414 f010f000 00001010
1f101f00 00000000 001f1400 00000000 00fc1400 00000000 f010f000 00000000
ff10ff00 00001010 14ff1400 00001414 101f0000 00001010 00f01000 00000000
ffffff00 0000ffff f0f0f000 0000f0f0 ff000000 0000ffff 00ffff00 00000000
0f0f0f00 00000f0f 44384400 00003844 4a4a3400 0000fc4a 02060600 00007e02
027e0200 0000027e 49416300 00006355 443c0400 00003844 201e2000 0000407e
7e020200 00000602 e7a59900 000099a5 492a1c00 00001c2a 01724c00 00004c72
4d4d3000 0000304a 78483000 00003048 5a463d00 0000bc62 49490000 00003e49
01017e00 00007e01 2a2a2a00 00002a2a 5f444400 00004444 4a444000 00004051
4a514000 00004044 ff010300 00000000 ff000000 0000e080 6b6b0800 00000808
36243600 00003612 090f0600 0000060f 18180000 00000000 10100000 00000000
ff010100 00003040 01011e00 0000001f 1d171200 00000019 3c3c3c00 0000003c
End CFunction
'
CFunction pix
00000000
8faa0010 8fab0014 8ce70000 240d0001 10ed000e 8fac0018 50e00008 8ca80000
240d0002 10ed0014 240d0003 54ed0021 8d460000 10000018 8ca20000 00001821
8cc20000 1000001a 00004821 8ca80000 00084027 8d420000 01024021 00001821
8cc20000 00021027 8d650000 00451021 1000000f 00004821 8ca20000 00004821
8cc80000 00084027 8d430000 01034021 10000007 00001821 00021027 8d630000
00431021 00004821 8cc80000 00001821 8d460000 14600004 24050001 0106302b
14c00003 30a500ff 00002821 30a500ff 10a00039 00082d82 8d660000 15200004
24050001 0046302b 14c00003 30a500ff 00002821 30a500ff 50a0002f 00082d82
8c840000 10800016 2404ffff 00002021 15200008 00002821 15200004 24060001
2c460020 10c00004 24060001 10000003 00462004 24060001 00462804 000830c0
01866021 8d860000 00c43025 ad860000 8d860004 00c52025 10000016 ad840004
15200009 2405ffff 15200004 24060001 2c460020 10c00005 24060001 00463004
10000004 00062027 24060001 00463004 00062827 000830c0 01866021 8d860000
00c43024 ad860000 8d860004 00c52024 ad840004 00082d82 00032280 00a42025
00084280 01021021 0048402b 00894821 03e00008 01091821
End CFunction
'
CFunction Sgetnextupdate
00000000
27bdffd0 afb6002c afb50028 afb40024 afb30020 afb2001c afb10018 afb00014
8fae0040 8fab0044 8fb20048 8fb1004c 8fad0050 24020040 a0820001 8dcf0000
8e420000 01e2102b 00004021 10400078 00004821 01e0c021 03af8021 27a20008
004fc821 8cec0000 8d620000 0182102b 50400067 27180001 01805021 000c98c0
02331021 8c430004 8c420000 afa20000 afa30004 01b39821 8e620000 8e630004
afa20008 afa3000c 0200a821 92030000 93220000 1062004c 0320b021 1000000f
acac0000 8e820008 8e83000c afa20000 afa30004 8e620008 8e63000c afa20008
afa3000c 26940008 92a30000 92c20000 10620040 26730008 acac0000 accf0000
adcf0000 acec0000 03b81021 90450000 90420008 10450028 24060001 8d620000
0142102b 10400024 01407821 000a60c0 022c8821 01ac6021 03b8c021 a3050008
000f78c0 01af7821 8fa20008 8fa3000c ade20000 ade30004 24c60001 00861021
a0450000 254a0001 8e220008 8e23000c afa20000 afa30004 8d820008 8d83000c
afa20008 afa3000c 8ce20000 24420001 ace20000 93050000 93020008 10450006
01407821 26310008 8d620000 0142102b 1440ffe2 258c0008 8ce30000 8d620000
54620006 a0860000 8dc20000 24420001 adc20000 ace00000 a0860000 00c04021
10000013 00064fc3 000c60c0 022ca021 01ac9821 ace00000 254a0001 8d620000
0142102b 1440ffaf 01406021 27180001 03007821 26100001 8e420000 0302102b
1440ff90 27390001 00004021 00004821 01001021 01201821 8fb6002c 8fb50028
8fb40024 8fb30020 8fb2001c 8fb10018 8fb00014 03e00008 27bd0030
End CFunction
'
CFunction ffr
00000000
27bdffc8 afb50034 afb40030 afb3002c afb20028 afb10024 afb00020 8fb10048
8fa80050 8fb00054 8fb90058 2402ffff a3a20008 2403fffe a3a30009 2403fffc
a3a3000a 2403fff8 a3a3000b 2403fff0 a3a3000c 2403ffe0 a3a3000d 2403ffc0
a3a3000e 2403ff80 a3a3000f 24030001 a3a30010 24030003 a3a30011 24030007
a3a30012 2403000f a3a30013 2403001f a3a30014 2403003f a3a30015 2403007f
a3a30016 a3a20017 8fa2004c 8c420000 24030001 50430023 8ca30000 50400008
8ca20000 24030002 10430037 24030003 5443006b 25a20007 10000050 8cc20000
00406021 8d030000 0043282b 00004021 10a000f4 00004821 2442ffff 8ce50000
00451021 0043c02b 2463ffff 0078100a 0040c021 8ccf0000 8e020000 01e2182b
106000e8 01e06821 25efffff 8e230000 01e37821 01e2182b 2442ffff 1000004f
0043c00a 00031827 8d020000 00621021 0040c021 00004021 044000da 00004821
8ce30000 00431023 24420001 284c0000 000c100b 00406021 8cc30000 00031827
8e020000 00621021 044000ce 00407821 8e2d0000 004d1023 244d0001 29a20000
10000036 0002680b 8d020000 8cc30000 00031827 00621821 0062c02b 2442ffff
0058180a 0060c021 8e220000 00621023 24420001 284c0000 000c100b 00406021
8ca20000 00406821 8e030000 0043282b 00004021 10a000b3 00004821 2442ffff
8ce50000 00451021 0043782b 2463ffff 006f100a 10000019 00407821 00406021
8d030000 0043302b 00004021 10c000a5 00004821 2442ffff 8e260000 00461021
0043c02b 2463ffff 0078100a 0040c021 8ca30000 00031827 8e020000 00621021
04400098 00407821 8ced0000 004d1023 244d0001 29a20000 0002680b 25a20007
29a90000 01a9100a 000248c3 25e20007 29f00000 01f0100a 000280c3 000990c0
01b29023 001040c0 15300028 01e84023 01803021 030c102b 14400024 03009821
000c28c0 03252821 03a8a821 03b2a021 03a93821 8ca20000 8ca30004 afa20000
afa30004 8c820000 10400008 00a08821 92820008 92ae0010 01c27024 90e20000
01c21025 10000009 a0e20000 92ae0010 92820008 01c27024 000e7027 31ce00ff
90e20000 01c21024 a0e20000 8fa20000 8fa30004 ae220000 ae230004 24c60001
0266102b 1040ffe3 24a50008 25330001 0213102b 14400030 0270102b 01803021
030c102b 1440002b 03008821 000c28c0 03252821 03b29021 03a94821 03a8a021
03b03821 8ca20000 8ca30004 afa20000 afa30004 8c820000 1040000a 00a04021
924b0008 91220000 01621025 a1220000 928a0010 90e20000 01421025 1000000d
a0e20000 924b0008 000b5827 316b00ff 91220000 01621024 a1220000 928a0010
000a5027 314a00ff 90e20000 01421024 a0e20000 8fa20000 8fa30004 ad020000
ad030004 24c60001 0226102b 1040ffdd 24a50008 0270102b 10400020 00001021
03b34021 03b08021 03004821 030c882b 000c90c0 03329021 2419ffff 16200014
01803021 02402821 8ca20000 8ca30004 afa20000 afa30004 8c820000 10400003
00a03821 10000002 a1190000 a1000000 8fa20000 8fa30004 ace20000 ace30004
24c60001 0126102b 1040ffef 24a50008 25080001 1510ffe9 00001021 7d823804
7f027a04 7da2bc04 7de2fe04 00001821 7d633804 7d437a04 7dc3bc04 00404021
00604821 01001021 01201821 8fb50034 8fb40030 8fb3002c 8fb20028 8fb10024
8fb00020 03e00008 27bd0038
End CFunction
 
viscomjim
Guru

Joined: 08/01/2014
Location: United States
Posts: 925
Posted: 08:17am 24 Nov 2014
Copy link to clipboard 
Print this post

Hi Matherp, this is excellent work. You have been hard at it and we thank you!! Could you give a brief description of how this is used? For instance, how do we display text within a program using this.

thanks again!!!
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2794
Posted: 10:23am 24 Nov 2014
Copy link to clipboard 
Print this post

BRILLIANT WORK Peter!

Will definitely be playing with your latest code as soon as possible.
Can't wait to see how 'fast' this all runs . . . .

Out of interest, where about in the UK are you?

WW
For everything Micromite visit micromite.org

Direct Email: whitewizzard@micromite.o
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2794
Posted: 02:42pm 24 Nov 2014
Copy link to clipboard 
Print this post

OK, partial success

I've copied & pasted the code - removed any 'phantom' spaces that appeared and run the program.

Starts of well (displaying all the shapes as they should appear) but when it comes to the text I get nothing at all (no errors reported - just a blank screen while it passes through the loops). The 'Main' loop then restarts correctly - once again showing the shapes; then blank for about 30seconds: this loop keeps going without error.

Any clues or advice to check for things I may have got wrong would be appreciated . . . .
I guess something wrong with the 'pstring' sub (or a sub that it calls)??

WW
For everything Micromite visit micromite.org

Direct Email: whitewizzard@micromite.o
 
micronut
Newbie

Joined: 03/09/2014
Location: United States
Posts: 37
Posted: 04:07pm 24 Nov 2014
Copy link to clipboard 
Print this post

matherp,

Great job! can you post the C source for the newest code as well? I want to try this on my spi based LCD during the long holiday weekend here in the States. Thanks!
 
     Page 1 of 2    
Print this page
© JAQ Software 2024